1 PACKAGE BODY WMS_XDOCK_PEGGING_PUB AS
2 /* $Header: WMSXDCKB.pls 120.29.12020000.4 2013/03/29 03:59:42 raminoch ship $ */
3
4
5 -- Global constants holding the package name and package version
6 g_pkg_name CONSTANT VARCHAR2(30) := 'WMS_XDOCK_PEGGING_PUB';
7 g_pkg_version CONSTANT VARCHAR2(100) := '$Header: WMSXDCKB.pls 120.29.12020000.4 2013/03/29 03:59:42 raminoch ship $';
8
9 -- This is the global cache table used to store the crossdock criteria records
10 -- encountered during crossdock pegging. This is defined solely in the package body
11 -- so only the procedures and functions in this package can access it directly.
12 -- Set, Get, Delete, and Clear functions will be provided for outside callers.
13 TYPE crossdock_criteria_tb IS TABLE OF wms_crossdock_criteria%ROWTYPE
14 INDEX BY BINARY_INTEGER;
15 g_crossdock_criteria_tb crossdock_criteria_tb;
16
17 -- For Wave Planning Crossdocking Simulation
18 TYPE wp_crossdock_rec IS RECORD(
19 delivery_detail_id number,
20 crossdock_qty number);
21
22
23 TYPE wp_crossdock_tbl IS TABLE OF wp_crossdock_rec INDEX BY BINARY_INTEGER;
24
25 x_wp_crossdock_tbl wp_crossdock_tbl;
26
27 -- This is the global cache table used to store the default routing ID for supplies
28 -- based on the item, org, and vendor. We do not want to include supply lines with a
29 -- routing ID of 3 = Direct. The available routing ID's are as follows:
30 -- 1. Standard 2. Inspect 3. Direct
31 TYPE routing_id_tb IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
32 g_item_routing_id_tb routing_id_tb;
33 g_org_routing_id_tb routing_id_tb;
34 g_vendor_routing_id_tb routing_id_tb;
35
36 -- The following types are used to cache the UOM conversions. The three keys to this
37 -- are the inventory item, from UOM code, and to UOM code. This will yield the conversion
38 -- rate by using a nested PLSQL table structure.
39 TYPE to_uom_code_tb IS TABLE OF NUMBER INDEX BY VARCHAR2(3);
40 TYPE from_uom_code_tb IS TABLE OF to_uom_code_tb INDEX BY VARCHAR2(3);
41 TYPE item_uom_conversion_tb IS TABLE OF from_uom_code_tb INDEX BY BINARY_INTEGER;
42 g_item_uom_conversion_tb item_uom_conversion_tb;
43
44 -- The following are global constants used in this package.
45
46 -- Allocation method for the current pick release batch
47 G_INVENTORY_ONLY CONSTANT VARCHAR2(1) := 'I';
48 G_CROSSDOCK_ONLY CONSTANT VARCHAR2(1) := 'C';
49 G_PRIORITIZE_INVENTORY CONSTANT VARCHAR2(1) := 'N';
50 G_PRIORITIZE_CROSSDOCK CONSTANT VARCHAR2(1) := 'X';
51
52 -- Types of sources
53 G_SRC_TYPE_SUP CONSTANT NUMBER := 1; -- Source type Supply
54 G_SRC_TYPE_DEM CONSTANT NUMBER := 2; -- Source type Demand
55
56 -- Crossdock criterion types
57 G_CRT_TYPE_OPP CONSTANT NUMBER := 1; -- Criterion type Opportunistic
58 G_CRT_TYPE_PLAN CONSTANT NUMBER := 2; -- Criterion type Planned
59
60 -- Crossdock criterion rule types
61 G_CRT_RULE_TYPE_OPP CONSTANT NUMBER := 10; -- Criterion Rule type Opportunistic
62 G_CRT_RULE_TYPE_PLAN CONSTANT NUMBER := 11; -- Criterion Rule type Planned
63
64 -- Scheduling methods
65 G_APPT_START_TIME CONSTANT NUMBER := 1; -- Start of dock appointment
66 G_APPT_MEAN_TIME CONSTANT NUMBER := 2; -- Mean of dock appointment
67 G_APPT_END_TIME CONSTANT NUMBER := 3; -- End of dock appointment
68
69 -- Crossdocking goals
70 G_MINIMIZE_WAIT CONSTANT NUMBER := 1; -- Minimize time between receipt and shipment
71 G_MAXIMIZE_XDOCK CONSTANT NUMBER := 2; -- Maximize time between receipt and shipment
72 G_CUSTOM_GOAL CONSTANT NUMBER := 3; -- Order supply/demand lines using custom logic
73
74 -- Supply sources for Planned Crossdock
75 G_PLAN_SUP_PO_APPR CONSTANT NUMBER := 10; -- Approved PO
76 G_PLAN_SUP_ASN CONSTANT NUMBER := 20; -- ASN
77 G_PLAN_SUP_REQ CONSTANT NUMBER := 30; -- Internal Req
78 G_PLAN_SUP_INTR CONSTANT NUMBER := 40; -- Intransit Shipments
79 G_PLAN_SUP_WIP CONSTANT NUMBER := 50; -- WIP
80 G_PLAN_SUP_RCV CONSTANT NUMBER := 60; -- Material in Receiving
81
82 -- Demand sources for Opportunistic Crossdock
83 G_OPP_DEM_SO_SCHED CONSTANT NUMBER := 10; -- Sales Order (Scheduled)
84 G_OPP_DEM_SO_BKORD CONSTANT NUMBER := 20; -- Sales Order (Backordered)
85 G_OPP_DEM_IO_SCHED CONSTANT NUMBER := 30; -- Internal Order (Scheduled)
86 G_OPP_DEM_IO_BKORD CONSTANT NUMBER := 40; -- Internal Order (Backordered)
87 G_OPP_DEM_WIP_BKORD CONSTANT NUMBER := 50; -- WIP Component Demand (Backordered)
88 l_simulation_mode varchar2(1) := 'N';
89
90 -- Procedure to print debug messages.
91 -- We will rely on the caller to this procedure to determine if debug logging
92 -- should be done or not instead of querying for the profile value every time.
93 PROCEDURE print_debug(p_debug_msg IN VARCHAR2)
94 IS
95 BEGIN
96 inv_mobile_helper_functions.tracelog
97 (p_err_msg => p_debug_msg,
98 p_module => 'WMS_XDock_Pegging_Pub',
99 p_level => 4);
100 END;
101
102
103 -- This function will store the crossdock criteria record inputted into the cache
104 -- {{******************** Crossdock Criteria Caching Functions ********************}}
105 FUNCTION set_crossdock_criteria
106 (p_criterion_id IN NUMBER) RETURN BOOLEAN
107 IS
108 BEGIN
109 IF (p_criterion_id IS NULL) THEN
110 RETURN FALSE;
111 END IF;
112
113 IF (g_crossdock_criteria_tb.EXISTS(p_criterion_id)) THEN
114 -- {{
115 -- Test setting the crossdock criteria record for a crossdock criterion that
116 -- is already cached. }}
117 RETURN TRUE;
118 ELSE
119 -- {{
120 -- Test setting the crossdock criteria record for a crossdock criterion that
121 -- has not yet been cached. }}
122 SELECT *
123 INTO g_crossdock_criteria_tb(p_criterion_id)
124 FROM wms_crossdock_criteria
125 WHERE criterion_id = p_criterion_id;
126 RETURN TRUE;
127 END IF;
128 EXCEPTION
129 WHEN OTHERS THEN
130 RETURN FALSE;
131 END set_crossdock_criteria;
132
133
134 -- This function will retrieve the crossdock criteria record inputted from the cache
135 FUNCTION get_crossdock_criteria
136 (p_criterion_id IN NUMBER) RETURN wms_crossdock_criteria%ROWTYPE
137 IS
138 BEGIN
139 IF (p_criterion_id IS NULL) THEN
140 RETURN NULL;
141 END IF;
142
143 IF (NOT g_crossdock_criteria_tb.EXISTS(p_criterion_id)) THEN
144 -- {{
145 -- Test retrieving a crossdock criteria record for a crossdock criterion that
146 -- has not yet been cached. }}
147 SELECT *
148 INTO g_crossdock_criteria_tb(p_criterion_id)
149 FROM wms_crossdock_criteria
150 WHERE criterion_id = p_criterion_id;
151 END IF;
152 -- {{
153 -- Test retrieving a crossdock criteria record for a crossdock criterion that
154 -- is already cached. }}
155 RETURN g_crossdock_criteria_tb(p_criterion_id);
156 EXCEPTION
157 WHEN OTHERS THEN
158 RETURN NULL;
159 END get_crossdock_criteria;
160
161
162 -- This function will delete the crossdock criteria record inputted from the cache
163 FUNCTION delete_crossdock_criteria
164 (p_criterion_id IN NUMBER) RETURN BOOLEAN
165 IS
166 BEGIN
167 IF (p_criterion_id IS NULL) THEN
168 RETURN FALSE;
169 END IF;
170
171 -- {{
172 -- Test deleting an existing crossdock criteria record from the cache. }}
173 -- {{
174 -- Test deleting a non-existing crossdock criteria record from the cache. }}
175 g_crossdock_criteria_tb.DELETE(p_criterion_id);
176 RETURN TRUE;
177 EXCEPTION
178 WHEN OTHERS THEN
179 RETURN FALSE;
180 END delete_crossdock_criteria;
181
182
183 -- This function will clear all of the crossdock criteria records stored in the cache
184 FUNCTION clear_crossdock_cache RETURN BOOLEAN
185 IS
186 BEGIN
187 -- {{
188 -- Test clearing the entire crossdock criteria cache. }}
189 g_crossdock_criteria_tb.DELETE;
190 RETURN TRUE;
191 EXCEPTION
192 WHEN OTHERS THEN
193 RETURN FALSE;
194 END clear_crossdock_cache;
195 -- {{ }}
196 -- {{******************** End Crossdock Criteria Caching Functions ********************}}
197 -- {{ }}
198
199
200 -- This is a function used to retrieve the default routing ID given an item, org,
201 -- and vendor as inputs. This function will use the same logic as the get_defaul_routing_id
202 -- in the INV_RCV_COMMON_APIS package. However we will cache all of the values retrieved
203 -- for performance. The order to search for a default routing ID is: item, vendor, org.
204 -- The org and item should always be inputted and be non-null.
205 -- {{ }}
206 -- {{******************** Function get_default_routing_id ********************}}
207 FUNCTION get_default_routing_id
208 (p_organization_id IN NUMBER,
209 p_item_id IN NUMBER,
210 p_vendor_id IN NUMBER
211 ) RETURN NUMBER DETERMINISTIC
212 IS
213 BEGIN
214 -- Get the default routing ID based on the item.
215 -- {{
216 -- Get the routing ID from the item when the info has been cached. }}
217 -- {{
218 -- Get the routing ID from the item when the info has not been cached. }}
219 IF (NOT g_item_routing_id_tb.EXISTS(p_item_id)) THEN
220 BEGIN
221 SELECT receiving_routing_id
222 INTO g_item_routing_id_tb(p_item_id)
223 FROM mtl_system_items
224 WHERE inventory_item_id = p_item_id
225 AND organization_id = p_organization_id;
226 EXCEPTION
227 WHEN NO_DATA_FOUND THEN
228 NULL;
229 WHEN OTHERS THEN
230 RAISE fnd_api.g_exc_unexpected_error;
231 END;
232 END IF;
233
234 -- Return the item default routing ID if a cached value exists
235 -- and is not null. A value might not exist in case of a
236 -- NO_DATA_FOUND exception in the query.
237 -- {{
238 -- Test for item routing ID exists but is NULL. Make sure we continue searching
239 -- for a routing ID at the other levels, i.e. vendor and org. }}
240 IF (g_item_routing_id_tb.EXISTS(p_item_id) AND
241 g_item_routing_id_tb(p_item_id) IS NOT NULL) THEN
242 RETURN g_item_routing_id_tb(p_item_id);
243 END IF;
244
245 -- Get the default routing ID based on the vendor
246 -- if a value is passed
247 -- {{
248 -- Get the routing ID from the vendor when the info has been cached. }}
249 -- {{
250 -- Get the routing ID from the vendor when the info has not been cached. }}
251 IF (p_vendor_id IS NOT NULL) THEN
252 IF (NOT g_vendor_routing_id_tb.EXISTS(p_vendor_id)) THEN
253 BEGIN
254 SELECT receiving_routing_id
255 INTO g_vendor_routing_id_tb(p_vendor_id)
256 FROM po_vendors
257 WHERE vendor_id = p_vendor_id;
258 EXCEPTION
259 WHEN NO_DATA_FOUND THEN
260 NULL;
261 WHEN OTHERS THEN
262 RAISE fnd_api.g_exc_unexpected_error;
263 END;
264 END IF;
265
266 -- Return the vendor default routing ID if a cached value exists
267 -- and is not null. A value might not exist in case of a
268 -- NO_DATA_FOUND exception in the query.
269 -- {{
270 -- Test for vendor routing ID exists but is NULL. Make sure we continue searching
271 -- for a routing ID at the other levels, i.e. org. }}
272 IF (g_vendor_routing_id_tb.EXISTS(p_vendor_id) AND
273 g_vendor_routing_id_tb(p_vendor_id) IS NOT NULL) THEN
274 RETURN g_vendor_routing_id_tb(p_vendor_id);
275 END IF;
276 END IF;
277
278 -- Get the default routing ID based on the org
279 -- {{
280 -- Get the routing ID from the org when the info has been cached. }}
281 -- {{
282 -- Get the routing ID from the org when the info has not been cached. }}
283 IF (NOT g_org_routing_id_tb.EXISTS(p_organization_id)) THEN
284 BEGIN
285 SELECT NVL(receiving_routing_id, 1)
286 INTO g_org_routing_id_tb(p_organization_id)
287 FROM rcv_parameters
288 WHERE organization_id = p_organization_id;
289 EXCEPTION
290 WHEN NO_DATA_FOUND THEN
291 NULL;
292 WHEN OTHERS THEN
293 RAISE fnd_api.g_exc_unexpected_error;
294 END;
295 END IF;
296
297 -- Return the org default routing ID if a cached value exists
298 -- and is not null. A value might not exist in case of a
299 -- NO_DATA_FOUND exception in the query.
300 -- {{
301 -- Test for org routing ID exists but is NULL. Make sure we continue searching
302 -- for a routing ID at the other levels. (In this case, there are no places left
303 -- to search for a routing ID). }}
304 IF (g_org_routing_id_tb.EXISTS(p_organization_id) AND
305 g_org_routing_id_tb(p_organization_id) IS NOT NULL) THEN
306 RETURN g_org_routing_id_tb(p_organization_id);
307 END IF;
308
309 -- This case should not happen but return 1 in case nothing
310 -- has been found so far.
311 -- {{
312 -- When no routing ID can be determined, a value of 1 should be returned. }}
313 RETURN 1;
314
315 EXCEPTION
316 WHEN OTHERS THEN
317 -- If an exception occurs, just return a value of 1 to indicate
318 -- Standard routing as the default.
319 RETURN 1;
320 END get_default_routing_id;
321 -- {{ }}
322 -- {{******************** End get_default_routing_id ********************}}
323 -- {{ }}
324
325
326 -- This is a function used to retrieve the UOM conversion rate given an inventory item ID,
327 -- from UOM code and to UOM code. The values retrieved will be cached in a global PLSQL table.
328 -- {{ }}
329 -- {{******************** Function get_conversion_rate ********************}}
330 FUNCTION get_conversion_rate
331 (p_item_id IN NUMBER,
332 p_from_uom_code IN VARCHAR2,
333 p_to_uom_code IN VARCHAR2
334 ) RETURN NUMBER
335 IS
336 l_conversion_rate NUMBER;
337 BEGIN
338 IF (p_from_uom_code = p_to_uom_code) THEN
339 -- No conversion necessary
340 l_conversion_rate := 1;
341 ELSE
342 -- Check if the conversion rate for the item/from UOM/to UOM combination is cached
343 IF (g_item_uom_conversion_tb.EXISTS(p_item_id) AND
344 g_item_uom_conversion_tb(p_item_id).EXISTS(p_from_uom_code) AND
345 g_item_uom_conversion_tb(p_item_id)(p_from_uom_code).EXISTS(p_to_uom_code))
346 THEN
347 -- Conversion rate is cached so just use the value
348 l_conversion_rate :=
349 g_item_uom_conversion_tb(p_item_id)(p_from_uom_code)(p_to_uom_code);
350 ELSE
351 -- Conversion rate is not cached so query and store the value
352 inv_convert.inv_um_conversion(from_unit => p_from_uom_code,
353 to_unit => p_to_uom_code,
354 item_id => p_item_id,
355 uom_rate => l_conversion_rate);
356 IF (l_conversion_rate > 0) THEN
357 -- Store the conversion rate and also the reverse conversion.
358 -- Do this only if the conversion rate returned is valid, i.e. not negative.
359 -- {{
360 -- Test having an exception when retrieving the UOM conversion rate. }}
361 g_item_uom_conversion_tb(p_item_id)(p_from_uom_code)(p_to_uom_code)
362 := l_conversion_rate;
363 g_item_uom_conversion_tb(p_item_id)(p_to_uom_code)(p_from_uom_code)
364 := 1 / l_conversion_rate;
365 END IF;
366 END IF;
367 END IF;
368
369 -- Return the conversion rate retrieved
370 RETURN l_conversion_rate;
371
372 EXCEPTION
373 WHEN OTHERS THEN
374 -- If an exception occurs, return a negative value.
375 -- The calling program should interpret this as an exception in retrieving
376 -- the UOM conversion rate.
377 RETURN -999;
378 END get_conversion_rate;
379 -- {{ }}
380 -- {{******************** End get_conversion_rate ********************}}
381 -- {{ }}
382
383
384 -- Function to see if the inputted WDD demand line is associated with an order line that
385 -- is tied to a WIP supply somehow. i.e. Either already crossdocked or through an existing
386 -- manual reservation with WIP as the supply for that demand. This is needed in case we
387 -- do not want to have order lines partially crossdocked to WIP and other supply types.
388 -- {{ }}
389 -- {{******************** Function is_demand_tied_to_wip ********************}}
390 FUNCTION is_demand_tied_to_wip
391 (p_organization_id IN NUMBER,
392 p_inventory_item_id IN NUMBER,
393 p_demand_type_id IN NUMBER,
394 p_demand_header_id IN NUMBER,
395 p_demand_line_id IN NUMBER
396 ) RETURN VARCHAR2
397 IS
398 l_wip_exists NUMBER;
399
400 BEGIN
401 -- See if there is an existing reservation tying a WIP supply to this demand order line.
402 -- {{
403 -- Test for an OE demand input that is tied to a WIP supply and one that is not. }}
404 BEGIN
405 SELECT 1
406 INTO l_wip_exists
407 FROM dual
408 WHERE EXISTS (SELECT reservation_id
409 FROM mtl_reservations
410 WHERE organization_id = p_organization_id
411 AND inventory_item_id = p_inventory_item_id
412 AND demand_source_type_id = p_demand_type_id
413 AND demand_source_header_id = p_demand_header_id
414 AND demand_source_line_id = p_demand_line_id
415 AND supply_source_type_id = inv_reservation_global.g_source_type_wip);
416 EXCEPTION
417 WHEN OTHERS THEN
418 -- This should be when no reservations are found
419 RETURN 'N';
420 END;
421
422 -- If a reservations exists tying a WIP supply to the demand, return 'Y'.
423 IF (l_wip_exists IS NOT NULL) THEN
424 RETURN 'Y';
425 ELSE
426 RETURN 'N';
427 END IF;
428
429 END is_demand_tied_to_wip;
430 -- {{ }}
431 -- {{******************** End is_demand_tied_to_wip ********************}}
432 -- {{ }}
433
434
435 -- Function to see if the inputted WDD demand line is associated with an order line that
436 -- is tied to a non-WIP and non-Inventory supply somehow. i.e. Either already crossdocked or
437 -- through an existing manual reservation with a non-WIP and non-Inventory supply for that
438 -- demand. This is needed in case we do not want to have order lines partially crossdocked
439 -- to WIP and other supply types.
440 -- {{ }}
441 -- {{******************** Function is_demand_tied_to_non_wip ********************}}
442 FUNCTION is_demand_tied_to_non_wip
443 (p_organization_id IN NUMBER,
444 p_inventory_item_id IN NUMBER,
445 p_demand_type_id IN NUMBER,
446 p_demand_header_id IN NUMBER,
447 p_demand_line_id IN NUMBER
448 ) RETURN VARCHAR2
449 IS
450 l_non_wip_exists NUMBER;
451
452 BEGIN
453 -- See if there is an existing reservation tying a non-WIP and non-Inventory supply
454 -- to this demand order line.
455 -- {{
456 -- Test for an OE demand input that is tied to a non-WIP and non-INV supply
457 -- and one that is not. }}
458 BEGIN
459 SELECT 1
460 INTO l_non_wip_exists
461 FROM dual
462 WHERE EXISTS (SELECT reservation_id
463 FROM mtl_reservations
464 WHERE organization_id = p_organization_id
465 AND inventory_item_id = p_inventory_item_id
466 AND demand_source_type_id = p_demand_type_id
467 AND demand_source_header_id = p_demand_header_id
468 AND demand_source_line_id = p_demand_line_id
469 AND supply_source_type_id <> inv_reservation_global.g_source_type_wip
470 AND supply_source_type_id <> inv_reservation_global.g_source_type_inv);
471 EXCEPTION
472 WHEN OTHERS THEN
473 -- This should be when no reservations are found
474 RETURN 'N';
475 END;
476
477 -- If a reservations exists tying a non-WIP and non-Inventory supply to the demand,
478 -- return 'Y'.
479 IF (l_non_wip_exists IS NOT NULL) THEN
480 RETURN 'Y';
481 ELSE
482 RETURN 'N';
483 END IF;
484
485 END is_demand_tied_to_non_wip;
486 -- {{ }}
487 -- {{******************** End is_demand_tied_to_non_wip ********************}}
488 -- {{ }}
489
490
491 -- This is a private procedure used to crossdock/split a WDD record during pegging.
492 -- A common procedure is created since this exact piece of code is called in two places
493 -- for satisfying existing reservations and newly created crossdock reservations.
494 -- {{ }}
495 -- {{******************** Procedure Crossdock_WDD ********************}}
496 PROCEDURE Crossdock_WDD
497 (p_log_prefix IN VARCHAR2,
498 p_crossdock_type IN NUMBER,
499 p_batch_id IN NUMBER,
500 p_wsh_release_table IN OUT NOCOPY WSH_PR_CRITERIA.relRecTabTyp,
501 p_trolin_delivery_ids IN OUT NOCOPY WSH_UTIL_CORE.Id_Tab_Type,
502 p_del_detail_id IN OUT NOCOPY WSH_PICK_LIST.DelDetTabTyp,
503 l_wdd_index IN OUT NOCOPY NUMBER,
504 l_debug IN OUT NOCOPY NUMBER,
505 l_inventory_item_id IN OUT NOCOPY NUMBER,
506 l_wdd_txn_qty IN OUT NOCOPY NUMBER,
507 l_atd_qty IN OUT NOCOPY NUMBER,
508 l_atd_wdd_qty IN OUT NOCOPY NUMBER,
509 l_atd_wdd_qty2 IN OUT NOCOPY NUMBER,
510 l_supply_uom_code IN OUT NOCOPY VARCHAR2,
511 l_demand_uom_code IN OUT NOCOPY VARCHAR2,
512 l_demand_uom_code2 IN OUT NOCOPY VARCHAR2,
513 l_conversion_rate IN OUT NOCOPY NUMBER,
514 l_conversion_precision IN NUMBER,
515 l_demand_line_detail_id IN OUT NOCOPY NUMBER,
516 l_index IN OUT NOCOPY NUMBER,
517 l_detail_id_tab IN OUT NOCOPY WSH_UTIL_CORE.id_tab_type,
518 l_action_prms IN OUT NOCOPY WSH_GLBL_VAR_STRCT_GRP.dd_action_parameters_rec_type,
519 l_action_out_rec IN OUT NOCOPY WSH_GLBL_VAR_STRCT_GRP.dd_action_out_rec_type,
520 l_split_wdd_id IN OUT NOCOPY NUMBER,
521 l_detail_info_tab IN OUT NOCOPY WSH_INTERFACE_EXT_GRP.Delivery_Details_Attr_Tbl_Type,
522 l_in_rec IN OUT NOCOPY WSH_INTERFACE_EXT_GRP.detailInRecType,
523 l_out_rec IN OUT NOCOPY WSH_INTERFACE_EXT_GRP.detailOutRecType,
524 l_mol_line_id IN OUT NOCOPY NUMBER,
525 l_split_wdd_index IN OUT NOCOPY NUMBER,
526 l_split_delivery_index IN OUT NOCOPY NUMBER,
527 l_split_wdd_rel_rec IN OUT NOCOPY WSH_PR_CRITERIA.relRecTyp,
528 l_allocation_method IN OUT NOCOPY VARCHAR2,
529 l_demand_qty IN OUT NOCOPY NUMBER,
530 l_demand_qty2 IN OUT NOCOPY NUMBER,
531 l_demand_atr_qty IN OUT NOCOPY NUMBER,
532 l_xdocked_wdd_index IN OUT NOCOPY NUMBER,
533 l_supply_type_id IN OUT NOCOPY NUMBER,
534 x_return_status IN OUT NOCOPY VARCHAR2,
535 x_msg_count IN OUT NOCOPY NUMBER,
536 x_msg_data IN OUT NOCOPY VARCHAR2,
537 x_error_code OUT NOCOPY VARCHAR2)
538 IS
539 l_progress VARCHAR2(10);
540
541 BEGIN
542 -- Check if we need to split the WDD record or not based on the ATD qty
543 IF (l_wdd_txn_qty > l_atd_qty) THEN
544
545 l_split_flag := 'Y'; -- Make the Split Flag as Y
546
547 --We need not update the Delivery Detail in case of Simulation.
548
549 IF (l_debug = 1) THEN
550 print_debug(p_log_prefix || 'WDD txn qty > ATD qty, so need to split the WDD record');
551 END IF;
552 -- Split the WDD record.
553 -- {{
554 -- Test for WDD record being split when crossdocking an existing reservation. }}
555
556 -- First convert l_atd_qty to the UOM on the WDD line
557 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
558 l_supply_uom_code, l_demand_uom_code);
559 IF (l_conversion_rate < 0) THEN
560 IF (l_debug = 1) THEN
561 print_debug(p_log_prefix || 'Error while obtaining UOM conversion rate for WDD');
562 END IF;
563 -- Raise an exception. The caller will do the rollback, cleanups,
564 -- and decide where to goto next.
565 x_error_code := 'UOM';
566 RAISE FND_API.G_EXC_ERROR;
567 END IF;
568 -- Round the converted quantity to the standard precision
569 l_atd_wdd_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
570 IF (l_debug = 1) THEN
571 print_debug(p_log_prefix || 'ATD qty in WDD UOM: => ' || l_atd_wdd_qty || ' ' ||
572 l_demand_uom_code);
573 END IF;
574 l_progress := '10';
575
576 -- Convert l_atd_qty to the secondary UOM on the WDD line if a value exists
577 IF (l_demand_uom_code2 IS NOT NULL) THEN
578 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
579 l_supply_uom_code, l_demand_uom_code2);
580 IF (l_conversion_rate < 0) THEN
581 IF (l_debug = 1) THEN
582 print_debug(p_log_prefix || 'Error while obtaining secondary UOM conversion rate for WDD');
583 END IF;
584 -- Raise an exception. The caller will do the rollback, cleanups,
585 -- and decide where to goto next.
586 x_error_code := 'UOM';
587 RAISE FND_API.G_EXC_ERROR;
588 END IF;
589 -- Round the converted quantity to the standard precision
590 l_atd_wdd_qty2 := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
591 ELSE
592 -- Secondary WDD UOM code is NULL
593 l_atd_wdd_qty2 := NULL;
594 END IF; -- End retrieving conversion rate
595 IF (l_debug = 1) THEN
596 print_debug(p_log_prefix || 'ATD qty in WDD secondary UOM: => ' || l_atd_wdd_qty2 || ' ' ||
597 l_demand_uom_code2);
598 END IF;
599 l_progress := '20';
600
601 -- Split the WDD line with the partial quantity allocated. The original WDD
602 -- line will retain the unallocated quantity.
603 l_detail_id_tab(1) := l_demand_line_detail_id;
604 l_action_prms.caller := 'WMS_XDOCK_PEGGING_PUB';
605 l_action_prms.action_code := 'SPLIT-LINE';
606 l_action_prms.split_quantity := l_atd_wdd_qty;
607 l_action_prms.split_quantity2 := l_atd_wdd_qty2;
608
609 IF (l_debug = 1) THEN
610 print_debug(p_log_prefix || 'Call the Delivery_Detail_Action API to split the WDD');
611 END IF;
612
613 if l_simulation_mode = 'N' then
614
615 WSH_INTERFACE_GRP.Delivery_Detail_Action
616 (p_api_version_number => 1.0,
617 p_init_msg_list => fnd_api.g_false,
618 p_commit => fnd_api.g_false,
619 x_return_status => x_return_status,
620 x_msg_count => x_msg_count,
621 x_msg_data => x_msg_data,
622 p_detail_id_tab => l_detail_id_tab,
623 p_action_prms => l_action_prms,
624 x_action_out_rec => l_action_out_rec
625 );
626
627 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
628 IF (l_debug = 1) THEN
629 print_debug(p_log_prefix || 'Error returned from Split Delivery_Detail_Action API: '
630 || x_return_status);
631 END IF;
632 -- Raise an exception. The caller will do the rollback, cleanups,
633 -- and decide where to goto next.
634 x_error_code := 'DB';
635 RAISE FND_API.G_EXC_ERROR;
636 END IF;
637 IF (l_debug = 1) THEN
638 print_debug(p_log_prefix || 'Successfully split the WDD record');
639 END IF;
640 l_progress := '30';
641
642 l_index := l_action_out_rec.result_id_tab.FIRST;
643 l_split_wdd_id := l_action_out_rec.result_id_tab(l_index);
644
645 end if;
646
647 -- Do the following logic only for Planned Crossdocking
648 IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
649 -- Insert the split WDD line into p_wsh_release_table.
650 -- The split WDD release record should be the same as the original one with
651 -- only the following fields modified: delivery_detail_id, released_status,
652 -- move_order_line_id (if supply used is receiving) and requested_quantity fields
653 l_split_wdd_rel_rec := p_wsh_release_table(l_wdd_index);
654 l_split_wdd_rel_rec.delivery_detail_id := l_split_wdd_id;
655 l_split_wdd_rel_rec.released_status := 'S';
656 l_split_wdd_rel_rec.move_order_line_id := l_mol_line_id;
657 l_split_wdd_rel_rec.requested_quantity := l_atd_wdd_qty;
658 l_split_wdd_rel_rec.requested_quantity2 := l_atd_wdd_qty2;
659
660 l_index := p_wsh_release_table.LAST + 1;
661 p_wsh_release_table(l_index) := l_split_wdd_rel_rec;
662 -- Store this newly inserted split WDD index value. In case of rollback,
663 -- we need to remove this record from p_wsh_release_table.
664 l_split_wdd_index := l_index;
665
666 -- Update the original WDD line in p_wsh_release_table with the current
667 -- unallocated quantity while retaining the original released_status
668 -- (should be 'R' or 'B'). Do this in the UOM of the WDD line and also update
669 -- the secondary requested quantity field.
670 p_wsh_release_table(l_wdd_index).requested_quantity := l_demand_qty - l_atd_wdd_qty;
671 p_wsh_release_table(l_wdd_index).requested_quantity2 := l_demand_qty2 - l_atd_wdd_qty2;
672
673 IF (l_debug = 1) THEN
674 print_debug(p_log_prefix || 'Updated the WDD records in p_wsh_release_table');
675 END IF;
676 END IF; -- End of: IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
677
678 -- Update the demand qty variable to indicate how much quantity on the original
679 -- WDD demand line is left to be crossdocked if not crossdocked already.
680 -- This is done here outside of the crossdock type loop so opportunistic crossdocking
681 -- can have visibility to how much of the WDD demand line was used for crossdock.
682 l_demand_qty := l_demand_qty - l_atd_wdd_qty;
683 l_demand_qty2 := l_demand_qty2 - l_atd_wdd_qty2;
684 -- Update the demand ATR qty variable if necessary.
685 -- This is needed for Planned Crossdocking when looping through the available supply lines
686 -- in case the WDD demand gets split. The unallocated WDD that loops again needs to have
687 -- the correct ATR qty otherwise the ATD qty calculated will be incorrect.
688 IF (l_demand_atr_qty IS NOT NULL) THEN
689 l_demand_atr_qty := l_demand_atr_qty - l_atd_wdd_qty;
690 ELSE
691 -- NULL value of demand ATR qty implies we are trying to satisfy an existing
692 -- reservation and there was no need to calculate the ATR qty on the demand line.
693 -- All of the qty on it should be reservable. In that case, we do not need to
694 -- update this variable since it isn't used. Doing it here for completeness.
695 l_demand_atr_qty := l_demand_qty;
696 END IF;
697 l_progress := '40';
698 ELSE
699 IF (l_debug = 1) THEN
700 print_debug(p_log_prefix || 'WDD txn qty = ATD qty, so no need to split the WDD record');
701 END IF;
702 -- {{
703 -- Test for WDD qty = available to detail qty. WDD record should be crossdocked
704 -- properly. }}
705
706 -- Do the following logic only for Planned Crossdocking
707 IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
708 -- Crossdock/Update the corresponding record in p_wsh_release_table
709 p_wsh_release_table(l_wdd_index).released_status := 'S';
710 p_wsh_release_table(l_wdd_index).move_order_line_id := l_mol_line_id;
711 END IF;
712
713 -- Set the split WDD ID. Even though the WDD record did not get split,
714 -- this variable is used later on to refer to the WDD ID that was crossdocked.
715 l_split_wdd_id := l_demand_line_detail_id;
716
717 -- Update the demand qty variable to indicate how much quantity on the original
718 -- WDD demand line is left to be crossdocked if not crossdocked already.
719 -- This is done here outside of the crossdock type loop so opportunistic crossdocking
720 -- can have visibility to how much of the WDD demand line was used for crossdock.
721 l_demand_qty := 0;
722 l_demand_qty2 := 0;
723 -- Update the demand ATR qty for completeness. This should not be required since
724 -- the WDD did not get split.
725 l_demand_atr_qty := 0;
726 l_split_flag := 'N';
727 l_progress := '50';
728 END IF; -- End splitting WDD record: Matches IF (l_wdd_txn_qty > l_atd_qty) THEN
729
730 -- Crossdock the WDD record with the allocated quantity.
731 -- Update the released_status to 'S' and update the move_order_line_id
732 -- column if the supply type used is Receiving.
733 IF (l_debug = 1) THEN
734 print_debug(p_log_prefix || 'Update the crossdocked WDD record: ' || l_split_wdd_id);
735 END IF;
736
737 -- Store the crossdocked WDD record to update in l_detail_info_tab.
738 -- The shipping API to update the table of WDD records will be done at the end
739 -- once all lines have been considered for crossdocking.
740 l_xdocked_wdd_index := l_detail_info_tab.COUNT + 1;
741 l_detail_info_tab(l_xdocked_wdd_index).delivery_detail_id := l_split_wdd_id;
742 l_detail_info_tab(l_xdocked_wdd_index).released_status := 'S';
743 -- For WIP supplies being crossdocked to a WDD demand, do not update
744 -- the move_order_line_id column. This is to mimic 11.5.10 and prior behavior.
745 IF (l_supply_type_id <> 5) THEN
746 l_detail_info_tab(l_xdocked_wdd_index).move_order_line_id := l_mol_line_id;
747 END IF;
748 -- For Planned Crossdocking, we also want to update the batch_id column in WDD
749 IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
750 l_detail_info_tab(l_xdocked_wdd_index).batch_id := p_batch_id;
751 END IF;
752
753 -- Do the following logic only for Planned Crossdocking
754 IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
755 -- Insert a new record into p_trolin_delivery_ids and p_del_detail_id
756 -- for the crossdocked WDD line if allocation method = N (Prioritize Inventory).
757 -- This needs to be done whether the crossdocked WDD is a newly split one, or a pre-existing
758 -- one in the release_table. Shipping does not populate the delivery tables with any info
759 -- so all crossdocked WDD records should have a record inserted there.
760 -- {{
761 -- Crossdocked WDD records should insert new records into the delivery tables for
762 -- allocation method of Prioritize Inventory. }}
763 IF (l_allocation_method = G_PRIORITIZE_INVENTORY) THEN
764 l_index := NVL(p_del_detail_id.LAST, 0) + 1;
765 p_del_detail_id(l_index) := l_split_wdd_id;
766 p_trolin_delivery_ids(l_index) := p_wsh_release_table(l_wdd_index).delivery_id;
767 -- Store this newly inserted delivery related index value. In case of rollback,
768 -- we need to remove these records from p_del_detail_id and p_trolin_delivery_ids.
769 l_split_delivery_index := l_index;
770 IF (l_debug = 1) THEN
771 print_debug(p_log_prefix || 'Inserted record into delivery tables for crossdocked WDD');
772 END IF;
773 END IF;
774 END IF;
775 l_progress := '60';
776
777 EXCEPTION
778 WHEN OTHERS THEN
779 x_return_status := fnd_api.g_ret_sts_error;
780 fnd_msg_pub.count_and_get(p_count => x_msg_count,
781 p_data => x_msg_data);
782 IF (l_debug = 1) THEN
783 print_debug(p_log_prefix || 'Exiting Crossdock_WDD - Execution error: ' ||
784 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
785 END IF;
786
787 END Crossdock_WDD;
788 -- {{ }}
789 -- {{******************** End Crossdock_WDD ********************}}
790 -- {{ }}
791
792
793 -- This is a private procedure used to crossdock/split an RSV record during
794 -- both Planned and Opportunistic crossdock pegging for existing reservations.
795 -- {{ }}
796 -- {{******************** Procedure Crossdock_RSV ********************}}
797 PROCEDURE Crossdock_RSV
798 (p_log_prefix IN VARCHAR2,
799 p_crossdock_type IN NUMBER,
800 l_debug IN OUT NOCOPY NUMBER,
801 l_inventory_item_id IN OUT NOCOPY NUMBER,
802 l_rsv_txn_qty IN OUT NOCOPY NUMBER,
803 l_atd_qty IN OUT NOCOPY NUMBER,
804 l_atd_rsv_qty IN OUT NOCOPY NUMBER,
805 l_atd_rsv_qty2 IN OUT NOCOPY NUMBER,
806 l_atd_prim_qty IN OUT NOCOPY NUMBER,
807 l_supply_uom_code IN OUT NOCOPY VARCHAR2,
808 l_rsv_uom_code IN OUT NOCOPY VARCHAR2,
809 l_rsv_uom_code2 IN OUT NOCOPY VARCHAR2,
810 l_primary_uom_code IN OUT NOCOPY VARCHAR2,
811 l_conversion_rate IN OUT NOCOPY NUMBER,
812 l_conversion_precision IN NUMBER,
813 l_original_rsv_rec IN OUT NOCOPY inv_reservation_global.mtl_reservation_rec_type,
814 l_rsv_id IN OUT NOCOPY NUMBER,
815 l_to_rsv_rec IN OUT NOCOPY inv_reservation_global.mtl_reservation_rec_type,
816 l_split_wdd_id IN OUT NOCOPY NUMBER,
817 l_crossdock_criteria_id IN OUT NOCOPY NUMBER,
818 l_demand_expected_time IN OUT NOCOPY DATE,
819 l_supply_expected_time IN OUT NOCOPY DATE,
820 l_original_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
821 l_split_rsv_id IN OUT NOCOPY NUMBER,
822 l_rsv_qty IN OUT NOCOPY NUMBER,
823 l_rsv_qty2 IN OUT NOCOPY NUMBER,
824 l_to_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
825 l_supply_type_id IN OUT NOCOPY NUMBER,
826 x_return_status IN OUT NOCOPY VARCHAR2,
827 x_msg_count IN OUT NOCOPY NUMBER,
828 x_msg_data IN OUT NOCOPY VARCHAR2,
829 x_error_code OUT NOCOPY VARCHAR2)
830 IS
831 l_progress VARCHAR2(10);
832
833 BEGIN
834 -- Check if we need to split the RSV record or not based on the ATD qty
835 IF (l_rsv_txn_qty > l_atd_qty) THEN
836 IF (l_debug = 1) THEN
837 print_debug(p_log_prefix || 'RSV txn qty > ATD qty, so need to split the RSV record');
838 END IF;
839 -- Split the RSV record.
840 -- {{
841 -- Test for RSV record being split when crossdocking an existing reservation. }}
842
843 -- First convert l_atd_qty to the UOM on the RSV line
844 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
845 l_supply_uom_code, l_rsv_uom_code);
846 IF (l_conversion_rate < 0) THEN
847 IF (l_debug = 1) THEN
848 print_debug(p_log_prefix || 'Error while obtaining UOM conversion rate for RSV');
849 END IF;
850 -- Raise an exception. The caller will do the rollback, cleanups,
851 -- and decide where to goto next.
852 x_error_code := 'UOM';
853 RAISE FND_API.G_EXC_ERROR;
854 END IF;
855 -- Round the converted quantity to the standard precision
856 l_atd_rsv_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
857 IF (l_debug = 1) THEN
858 print_debug(p_log_prefix || 'ATD qty in RSV UOM: => ' || l_atd_rsv_qty || ' ' ||
859 l_rsv_uom_code);
860 END IF;
861 l_progress := '10';
862
863 -- Convert l_atd_qty to the secondary UOM on the RSV line if a value exists
864 IF (l_rsv_uom_code2 IS NOT NULL) THEN
865 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
866 l_supply_uom_code, l_rsv_uom_code2);
867 IF (l_conversion_rate < 0) THEN
868 IF (l_debug = 1) THEN
869 print_debug(p_log_prefix || 'Error while obtaining secondary UOM conversion rate for RSV');
870 END IF;
871 -- Raise an exception. The caller will do the rollback, cleanups,
872 -- and decide where to goto next.
873 x_error_code := 'UOM';
874 RAISE FND_API.G_EXC_ERROR;
875 END IF;
876 -- Round the converted quantity to the standard precision
877 l_atd_rsv_qty2 := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
878 ELSE
879 -- Secondary RSV UOM code is NULL
880 l_atd_rsv_qty2 := NULL;
881 END IF; -- End retrieving conversion rate
882 IF (l_debug = 1) THEN
883 print_debug(p_log_prefix || 'ATD qty in secondary RSV UOM: => ' || l_atd_rsv_qty2 || ' ' ||
884 l_rsv_uom_code2);
885 END IF;
886 l_progress := '20';
887
888 -- Do not modify the reservation if the supply is of type WIP.
889 -- We just want to update the l_rsv_qty and l_rsv_qty2 quantities.
890 IF (l_supply_type_id = 5) THEN
891 IF (l_debug = 1) THEN
892 print_debug(p_log_prefix || 'Do not modify the WIP as supply reservation');
893 END IF;
894 ELSE
895 -- Split the reservation with the quantity allocated. The original RSV record
896 -- will be the non-crossdocked one.
897 l_original_rsv_rec.reservation_id := l_rsv_id;
898
899 l_to_rsv_rec.demand_source_line_detail := l_split_wdd_id;
900 l_to_rsv_rec.reservation_quantity := l_atd_rsv_qty;
901 l_to_rsv_rec.reservation_uom_code := l_rsv_uom_code;
902 l_to_rsv_rec.secondary_reservation_quantity := l_atd_rsv_qty2;
903 l_to_rsv_rec.secondary_uom_code := l_rsv_uom_code2;
904 l_to_rsv_rec.primary_reservation_quantity := l_atd_prim_qty;
905 l_to_rsv_rec.primary_uom_code := l_primary_uom_code;
906 l_to_rsv_rec.crossdock_flag := 'Y';
907 l_to_rsv_rec.crossdock_criteria_id := l_crossdock_criteria_id;
908 l_to_rsv_rec.demand_ship_date := l_demand_expected_time;
909 l_to_rsv_rec.supply_receipt_date := l_supply_expected_time;
910
911 IF (l_debug = 1) THEN
912 print_debug(p_log_prefix || 'Call the transfer_reservation API to split the RSV record');
913 END IF;
914 INV_RESERVATION_PVT.transfer_reservation
915 (p_api_version_number => 1.0,
916 p_init_msg_lst => fnd_api.g_false,
917 x_return_status => x_return_status,
918 x_msg_count => x_msg_count,
919 x_msg_data => x_msg_data,
920 p_original_rsv_rec => l_original_rsv_rec,
921 p_to_rsv_rec => l_to_rsv_rec,
922 p_original_serial_number => l_original_serial_number,
923 p_validation_flag => fnd_api.g_true,
924 x_reservation_id => l_split_rsv_id);
925
926 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
927 IF (l_debug = 1) THEN
928 print_debug(p_log_prefix || 'Error returned from transfer_reservation API: '
929 || x_return_status);
930 END IF;
931 -- Raise an exception. The caller will do the rollback, cleanups,
932 -- and decide where to goto next.
933 x_error_code := 'DB';
934 RAISE FND_API.G_EXC_ERROR;
935 END IF;
936 IF (l_debug = 1) THEN
937 print_debug(p_log_prefix || 'Successfully split the RSV record');
938 END IF;
939 END IF;
940
941 -- Decrement the reservation qty variable so we know how much qty is left on the
942 -- original reservation to satisfy
943 l_rsv_qty := l_rsv_qty - l_atd_rsv_qty;
944 l_rsv_qty2 := l_rsv_qty2 - l_atd_rsv_qty2;
945 l_progress := '30';
946 ELSE
947 IF (l_debug = 1) THEN
948 print_debug(p_log_prefix || 'RSV txn qty = ATD qty, so no need to split the RSV record');
949 END IF;
950 -- l_rsv_txn_qty = l_atd_qty so just crossdock the RSV record.
951 -- Update the demand_source_line_detail column to the current WDD, set
952 -- crossdock_flag = 'Y', update the expected ship and receipt dates, and update
953 -- the crossdock criteria column.
954 -- {{
955 -- Test for RSV qty = available to detail qty. Reservation should be crossdocked
956 -- properly. }}
957
958 -- Do not modify the reservation if the supply is of type WIP.
959 -- We just want to update the l_rsv_qty and l_rsv_qty2 quantities.
960 IF (l_supply_type_id = 5) THEN
961 IF (l_debug = 1) THEN
962 print_debug(p_log_prefix || 'Do not modify the WIP as supply reservation');
963 END IF;
964 ELSE
965 l_original_rsv_rec.reservation_id := l_rsv_id;
966
967 l_to_rsv_rec.demand_source_line_detail := l_split_wdd_id;
968 l_to_rsv_rec.crossdock_flag := 'Y';
969 l_to_rsv_rec.crossdock_criteria_id := l_crossdock_criteria_id;
970 l_to_rsv_rec.demand_ship_date := l_demand_expected_time;
971 l_to_rsv_rec.supply_receipt_date := l_supply_expected_time;
972
973 IF (l_debug = 1) THEN
974 print_debug(p_log_prefix || 'Call the update_reservation API to crossdock the RSV record');
975 END IF;
976 INV_RESERVATION_PVT.update_reservation
977 (p_api_version_number => 1.0,
978 p_init_msg_lst => fnd_api.g_false,
979 x_return_status => x_return_status,
980 x_msg_count => x_msg_count,
981 x_msg_data => x_msg_data,
982 p_original_rsv_rec => l_original_rsv_rec,
983 p_to_rsv_rec => l_to_rsv_rec,
984 p_original_serial_number => l_original_serial_number,
985 p_to_serial_number => l_to_serial_number,
986 p_validation_flag => fnd_api.g_true,
987 p_check_availability => fnd_api.g_false);
988
989 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
990 IF (l_debug = 1) THEN
991 print_debug(p_log_prefix || 'Error returned from update_reservation API: '
992 || x_return_status);
993 END IF;
994 -- Raise an exception. The caller will do the rollback, cleanups,
995 -- and decide where to goto next.
996 x_error_code := 'DB';
997 RAISE FND_API.G_EXC_ERROR;
998 END IF;
999 IF (l_debug = 1) THEN
1000 print_debug(p_log_prefix || 'Successfully updated and crossdocked the RSV record');
1001 END IF;
1002 END IF;
1003
1004 -- Set the reservation qty to 0 indicating the reservation was fully consumed
1005 l_rsv_qty := 0;
1006 l_rsv_qty2 := 0;
1007 l_progress := '40';
1008 END IF; -- End crossdocking RSV record: Matches 'IF (l_rsv_txn_qty > l_atd_qty) THEN'
1009
1010 EXCEPTION
1011 WHEN OTHERS THEN
1012 x_return_status := fnd_api.g_ret_sts_error;
1013 fnd_msg_pub.count_and_get(p_count => x_msg_count,
1014 p_data => x_msg_data);
1015 IF (l_debug = 1) THEN
1016 print_debug(p_log_prefix || 'Exiting Crossdock_RSV - Execution error: ' ||
1017 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
1018 END IF;
1019
1020 END Crossdock_RSV;
1021 -- {{ }}
1022 -- {{******************** End Crossdock_RSV ********************}}
1023 -- {{ }}
1024
1025
1026 -- This is a private procedure used to crossdock/split a MOL record during pegging.
1027 -- A common procedure is created since this exact piece of code is called in two places
1028 -- for satisfying existing reservations and newly created crossdock reservations.
1029 -- {{ }}
1030 -- {{******************** Procedure Crossdock_MOL ********************}}
1031 PROCEDURE Crossdock_MOL
1032 (p_log_prefix IN VARCHAR2,
1033 p_crossdock_type IN NUMBER,
1034 l_debug IN OUT NOCOPY NUMBER,
1035 l_inventory_item_id IN OUT NOCOPY NUMBER,
1036 l_mol_qty IN OUT NOCOPY NUMBER,
1037 l_mol_qty2 IN OUT NOCOPY NUMBER,
1038 l_atd_qty IN OUT NOCOPY NUMBER,
1039 l_atd_mol_qty2 IN OUT NOCOPY NUMBER,
1040 l_supply_uom_code IN OUT NOCOPY VARCHAR2,
1041 l_mol_uom_code2 IN OUT NOCOPY VARCHAR2,
1042 l_conversion_rate IN OUT NOCOPY NUMBER,
1043 l_conversion_precision IN NUMBER,
1044 l_mol_prim_qty IN OUT NOCOPY NUMBER,
1045 l_atd_prim_qty IN OUT NOCOPY NUMBER,
1046 l_split_wdd_id IN OUT NOCOPY NUMBER,
1047 l_mol_header_id IN OUT NOCOPY NUMBER,
1048 l_mol_line_id IN OUT NOCOPY NUMBER,
1049 l_supply_atr_qty IN OUT NOCOPY NUMBER,
1050 l_demand_type_id IN OUT NOCOPY NUMBER,
1051 l_wip_entity_id IN OUT NOCOPY NUMBER,
1052 l_operation_seq_num IN OUT NOCOPY NUMBER,
1053 l_repetitive_schedule_id IN OUT NOCOPY NUMBER,
1054 l_wip_supply_type IN OUT NOCOPY NUMBER,
1055 l_xdocked_wdd_index IN OUT NOCOPY NUMBER,
1056 l_detail_info_tab IN OUT NOCOPY WSH_INTERFACE_EXT_GRP.Delivery_Details_Attr_Tbl_Type,
1057 l_wdd_index IN OUT NOCOPY NUMBER,
1058 l_split_wdd_index IN OUT NOCOPY NUMBER,
1059 p_wsh_release_table IN OUT NOCOPY WSH_PR_CRITERIA.relRecTabTyp,
1060 l_supply_type_id IN OUT NOCOPY NUMBER,
1061 x_return_status IN OUT NOCOPY VARCHAR2,
1062 x_msg_count IN OUT NOCOPY NUMBER,
1063 x_msg_data IN OUT NOCOPY VARCHAR2,
1064 x_error_code OUT NOCOPY VARCHAR2,
1065 x_new_mol_id OUT NOCOPY NUMBER,
1066 l_criterion_type IN NUMBER DEFAULT NULL)
1067 IS
1068 l_progress VARCHAR2(10);
1069 l_backorder_detail_id NUMBER;
1070 l_crossdock_type NUMBER;
1071 l_split_mol_line_id NUMBER;
1072
1073 BEGIN
1074
1075
1076 -- Set the value 'mtrl.backorder_delivery_detail_id' should be updated to
1077 -- based on OE or WIP demand.
1078 -- {{
1079 -- Test crossdocking a MOL to a demand of type WIP and OE for
1080 -- opportunistic crossdocking. }}
1081 IF (l_demand_type_id = 5) THEN
1082 -- WIP backordered component demand
1083 l_backorder_detail_id := l_wip_entity_id;
1084 l_crossdock_type := 2;
1085 ELSE
1086 -- OE demand
1087 l_backorder_detail_id := l_split_wdd_id;
1088 l_crossdock_type := 1;
1089 END IF;
1090
1091 -- Check if we need to split the MOL record or not based on the ATD qty
1092 IF (l_mol_qty > l_atd_qty) THEN
1093 IF (l_debug = 1) THEN
1094 print_debug(p_log_prefix || 'MOL qty > ATD qty, so need to split the MOL record');
1095 END IF;
1096 -- Split the MOL record.
1097 -- {{
1098 -- Test for splitting a MOL record for an existing reservation using
1099 -- In Receiving as the supply line source. }}
1100
1101 -- Convert l_atd_qty to the secondary UOM on the MOL line if a value exists
1102 IF (l_mol_uom_code2 IS NOT NULL) THEN
1103 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
1104 l_supply_uom_code, l_mol_uom_code2);
1105 IF (l_conversion_rate < 0) THEN
1106 IF (l_debug = 1) THEN
1107 print_debug(p_log_prefix || 'Error while obtaining UOM2 conversion rate for MOL');
1108 END IF;
1109 -- Raise an exception. The caller will do the rollback, cleanups,
1110 -- and decide where to goto next.
1111 x_error_code := 'UOM';
1112 RAISE FND_API.G_EXC_ERROR;
1113 END IF;
1114 -- Round the converted quantity to the standard precision
1115 l_atd_mol_qty2 := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
1116 ELSE
1117 -- Secondary RSV UOM code is NULL
1118 l_atd_mol_qty2 := NULL;
1119 END IF; -- End retrieving conversion rate
1120 IF (l_debug = 1) THEN
1121 print_debug(p_log_prefix || 'ATD qty in secondary MOL UOM: => ' || l_atd_mol_qty2 || ' ' ||
1122 l_mol_uom_code2);
1123 END IF;
1124 l_progress := '10';
1125
1126 -- Insert the new split MOL record which will be crossdocked with the
1127 -- the available to detail quantity.
1128 -- Note I would use a MERGE statement to do the INSERT and UPDATE in one SQL
1129 -- call. However, this has a limitation where the INSERT clause does not work
1130 -- with a subquery which is how we are inserting the split MOL record.
1131 -- The alternative is to store each of the columns in a variable but that
1132 -- is not ideal.
1133 BEGIN
1134 INSERT INTO mtl_txn_request_lines
1135 (LINE_ID
1136 ,HEADER_ID
1137 ,LINE_NUMBER
1138 ,ORGANIZATION_ID
1139 ,INVENTORY_ITEM_ID
1140 ,REVISION
1141 ,FROM_SUBINVENTORY_CODE
1142 ,FROM_LOCATOR_ID
1143 ,TO_SUBINVENTORY_CODE
1144 ,TO_LOCATOR_ID
1145 ,TO_ACCOUNT_ID
1146 ,LOT_NUMBER
1147 ,SERIAL_NUMBER_START
1148 ,SERIAL_NUMBER_END
1149 ,UOM_CODE
1150 ,QUANTITY
1151 ,QUANTITY_DELIVERED
1152 ,QUANTITY_DETAILED
1153 ,DATE_REQUIRED
1154 ,REASON_ID
1155 ,REFERENCE
1156 ,REFERENCE_TYPE_CODE
1157 ,REFERENCE_ID
1158 ,PROJECT_ID
1159 ,TASK_ID
1160 ,TRANSACTION_HEADER_ID
1161 ,LINE_STATUS
1162 ,STATUS_DATE
1163 ,LAST_UPDATED_BY
1164 ,LAST_UPDATE_LOGIN
1165 ,LAST_UPDATE_DATE
1166 ,CREATED_BY
1167 ,CREATION_DATE
1168 ,REQUEST_ID
1169 ,PROGRAM_APPLICATION_ID
1170 ,PROGRAM_ID
1171 ,PROGRAM_UPDATE_DATE
1172 ,ATTRIBUTE1
1173 ,ATTRIBUTE2
1174 ,ATTRIBUTE3
1175 ,ATTRIBUTE4
1176 ,ATTRIBUTE5
1177 ,ATTRIBUTE6
1178 ,ATTRIBUTE7
1179 ,ATTRIBUTE8
1180 ,ATTRIBUTE9
1181 ,ATTRIBUTE10
1182 ,ATTRIBUTE11
1183 ,ATTRIBUTE12
1184 ,ATTRIBUTE13
1185 ,ATTRIBUTE14
1186 ,ATTRIBUTE15
1187 ,ATTRIBUTE_CATEGORY
1188 ,TXN_SOURCE_ID
1189 ,TXN_SOURCE_LINE_ID
1190 ,TXN_SOURCE_LINE_DETAIL_ID
1191 ,TRANSACTION_TYPE_ID
1192 ,TRANSACTION_SOURCE_TYPE_ID
1193 ,PRIMARY_QUANTITY
1194 ,TO_ORGANIZATION_ID
1195 ,PUT_AWAY_STRATEGY_ID
1196 ,PICK_STRATEGY_ID
1197 ,SHIP_TO_LOCATION_ID
1198 ,UNIT_NUMBER
1199 ,REFERENCE_DETAIL_ID
1200 ,ASSIGNMENT_ID
1201 ,FROM_COST_GROUP_ID
1202 ,TO_COST_GROUP_ID
1203 ,LPN_ID
1204 ,TO_LPN_ID
1205 ,PICK_SLIP_NUMBER
1206 ,PICK_SLIP_DATE
1207 ,INSPECTION_STATUS
1208 ,PICK_METHODOLOGY_ID
1209 ,CONTAINER_ITEM_ID
1210 ,CARTON_GROUPING_ID
1211 ,BACKORDER_DELIVERY_DETAIL_ID
1212 ,WMS_PROCESS_FLAG
1213 ,SHIP_SET_ID
1214 ,SHIP_MODEL_ID
1215 ,MODEL_QUANTITY
1216 ,FROM_SUBINVENTORY_ID
1217 ,TO_SUBINVENTORY_ID
1218 ,CROSSDOCK_TYPE
1219 ,REQUIRED_QUANTITY
1220 ,GRADE_CODE
1221 ,SECONDARY_QUANTITY
1222 ,SECONDARY_QUANTITY_DELIVERED
1223 ,SECONDARY_QUANTITY_DETAILED
1224 ,SECONDARY_REQUIRED_QUANTITY
1225 ,SECONDARY_UOM_CODE
1226 ,WIP_ENTITY_ID
1227 ,REPETITIVE_SCHEDULE_ID
1228 ,OPERATION_SEQ_NUM
1229 ,WIP_SUPPLY_TYPE
1230 )
1231 (SELECT
1232 mtl_txn_request_lines_s.NEXTVAL -- LINE_ID
1233 ,HEADER_ID
1234 ,mtrl_max.line_num --LINE_NUMBER
1235 ,ORGANIZATION_ID
1236 ,INVENTORY_ITEM_ID
1237 ,REVISION
1238 ,FROM_SUBINVENTORY_CODE
1239 ,FROM_LOCATOR_ID
1240 ,TO_SUBINVENTORY_CODE
1241 ,TO_LOCATOR_ID
1242 ,TO_ACCOUNT_ID
1243 ,LOT_NUMBER
1244 ,SERIAL_NUMBER_START
1245 ,SERIAL_NUMBER_END
1246 ,UOM_CODE
1247 ,l_atd_qty --QUANTITY
1248 ,QUANTITY_DELIVERED
1249 ,QUANTITY_DETAILED
1250 ,DATE_REQUIRED
1251 ,REASON_ID
1252 ,REFERENCE
1253 ,REFERENCE_TYPE_CODE
1254 ,REFERENCE_ID
1255 ,PROJECT_ID
1256 ,TASK_ID
1257 ,TRANSACTION_HEADER_ID
1258 ,LINE_STATUS
1259 ,STATUS_DATE
1260 ,LAST_UPDATED_BY
1261 ,LAST_UPDATE_LOGIN
1262 ,SYSDATE --LAST_UPDATE_DATE
1263 ,CREATED_BY
1264 ,SYSDATE --CREATION_DATE
1265 ,REQUEST_ID
1266 ,PROGRAM_APPLICATION_ID
1267 ,PROGRAM_ID
1268 ,PROGRAM_UPDATE_DATE
1269 ,ATTRIBUTE1
1270 ,ATTRIBUTE2
1271 ,ATTRIBUTE3
1272 ,ATTRIBUTE4
1273 ,ATTRIBUTE5
1274 ,ATTRIBUTE6
1275 ,ATTRIBUTE7
1276 ,ATTRIBUTE8
1277 ,ATTRIBUTE9
1278 ,ATTRIBUTE10
1279 ,ATTRIBUTE11
1280 ,ATTRIBUTE12
1281 ,ATTRIBUTE13
1282 ,ATTRIBUTE14
1283 ,ATTRIBUTE15
1284 ,ATTRIBUTE_CATEGORY
1285 ,TXN_SOURCE_ID
1286 ,TXN_SOURCE_LINE_ID
1287 ,TXN_SOURCE_LINE_DETAIL_ID
1288 ,TRANSACTION_TYPE_ID
1289 ,TRANSACTION_SOURCE_TYPE_ID
1290 ,l_atd_prim_qty --PRIMARY_QUANTITY
1291 ,TO_ORGANIZATION_ID
1292 ,PUT_AWAY_STRATEGY_ID
1293 ,PICK_STRATEGY_ID
1294 ,SHIP_TO_LOCATION_ID
1295 ,UNIT_NUMBER
1296 -- Change made for Inbound. For Opportunistic cases inbound
1297 -- can call crossdock API for a particular MOL. Then they need
1298 -- to know the MOLs that have been split and created for this
1299 -- line so that they can requery them somehow for creating suggestions.
1300 ,Decode(l_criterion_type,g_crt_type_opp,l_mol_line_id,reference_detail_id)
1301 ,ASSIGNMENT_ID
1302 ,FROM_COST_GROUP_ID
1303 ,TO_COST_GROUP_ID
1304 ,LPN_ID
1305 ,TO_LPN_ID
1306 ,PICK_SLIP_NUMBER
1307 ,PICK_SLIP_DATE
1308 ,INSPECTION_STATUS
1309 ,PICK_METHODOLOGY_ID
1310 ,CONTAINER_ITEM_ID
1311 ,CARTON_GROUPING_ID
1312 ,l_backorder_detail_id --BACKORDER_DELIVERY_DETAIL_ID
1313 ,WMS_PROCESS_FLAG
1314 ,SHIP_SET_ID
1315 ,SHIP_MODEL_ID
1316 ,MODEL_QUANTITY
1317 ,FROM_SUBINVENTORY_ID
1318 ,TO_SUBINVENTORY_ID
1319 ,l_crossdock_type --CROSSDOCK_TYPE
1320 ,REQUIRED_QUANTITY
1321 ,GRADE_CODE
1322 ,l_atd_mol_qty2 --SECONDARY_QUANTITY
1323 ,SECONDARY_QUANTITY_DELIVERED
1324 ,SECONDARY_QUANTITY_DETAILED
1325 ,SECONDARY_REQUIRED_QUANTITY
1326 ,SECONDARY_UOM_CODE
1327 ,l_wip_entity_id --WIP_ENTITY_ID
1328 ,l_repetitive_schedule_id --REPETITIVE_SCHEDULE_ID
1329 ,l_operation_seq_num --OPERATION_SEQ_NUM
1330 ,l_wip_supply_type --WIP_SUPPLY_TYPE
1331 FROM mtl_txn_request_lines mtrl, (SELECT MAX(line_number) + 1 AS line_num
1332 FROM mtl_txn_request_lines
1333 WHERE header_id = l_mol_header_id) mtrl_max
1334 WHERE mtrl.line_id = l_mol_line_id);
1335 EXCEPTION
1336 WHEN OTHERS THEN
1337 IF (l_debug = 1) THEN
1338 print_debug(p_log_prefix || 'Error inserting split MOL record');
1339 END IF;
1340 -- Raise an exception. The caller will do the rollback, cleanups,
1341 -- and decide where to goto next.
1342 x_error_code := 'DB';
1343 RAISE FND_API.G_EXC_ERROR;
1344 END; -- End inserting split MOL record into MTL_TXN_REQUEST_LINES
1345
1346 -- Retrieve the split MOL line ID we have just inserted above.
1347 -- We cannot use the RETURNING clause since a sub-query was used for the insert.
1348 -- As of 10g, this is not a supported feature.
1349 BEGIN
1350 SELECT line_id
1351 INTO l_split_mol_line_id
1352 FROM mtl_txn_request_lines
1353 WHERE header_id = l_mol_header_id
1354 AND ROWNUM = 1
1355 ORDER BY line_number DESC;
1356 EXCEPTION
1357 WHEN OTHERS THEN
1358 IF (l_debug = 1) THEN
1359 print_debug(p_log_prefix || 'Error retrieving the split MOL line ID');
1360 END IF;
1361 -- Raise an exception. The caller will do the rollback, cleanups,
1362 -- and decide where to goto next.
1363 x_error_code := 'DB';
1364 RAISE FND_API.G_EXC_ERROR;
1365 END;
1366 IF (l_debug = 1) THEN
1367 print_debug(p_log_prefix || 'Successfully inserted/split the MOL record: ' ||
1368 l_split_mol_line_id);
1369 END IF;
1370
1371 -- Update the quantity on the original MOL record.
1372 BEGIN
1373 UPDATE mtl_txn_request_lines SET
1374 quantity = l_mol_qty - l_atd_qty,
1375 primary_quantity = l_mol_prim_qty - l_atd_prim_qty,
1376 secondary_quantity = l_mol_qty2 - l_atd_mol_qty2
1377 WHERE line_id = l_mol_line_id;
1378 EXCEPTION
1379 WHEN OTHERS THEN
1380 IF (l_debug = 1) THEN
1381 print_debug(p_log_prefix || 'Error updating the original MOL record');
1382 END IF;
1383 -- Raise an exception. The caller will do the rollback, cleanups,
1384 -- and decide where to goto next.
1385 x_error_code := 'DB';
1386 RAISE FND_API.G_EXC_ERROR;
1387 END;
1388
1389 -- Update the MOL qty values to indicate how much quantity from the original MOL
1390 -- is still available for crossdocking.
1391 l_mol_qty := l_mol_qty - l_atd_qty;
1392 l_mol_prim_qty := l_mol_prim_qty - l_atd_prim_qty;
1393 l_mol_qty2 := l_mol_qty2 - l_atd_mol_qty2;
1394 -- Do the following logic only for Opportunistic Crossdocking.
1395 -- This is needed so we can tell if the MOL supply line has been fully
1396 -- crossdocked yet.
1397 IF (p_crossdock_type = G_CRT_TYPE_OPP) THEN
1398 l_supply_atr_qty := l_supply_atr_qty - l_atd_qty;
1399 END IF;
1400
1401 IF (l_debug = 1) THEN
1402 print_debug(p_log_prefix || 'Successfully updated and crossdocked the MOL record');
1403 END IF;
1404 l_progress := '20';
1405 ELSE
1406 IF (l_debug = 1) THEN
1407 print_debug(p_log_prefix || 'MOL qty = ATD qty, so no need to split the MOL record');
1408 END IF;
1409 -- l_mol_qty = l_atd_qty so just crossdock the MOL record.
1410 -- Update the backorder_delivery_detail_id column and set the crossdock_type
1411 -- to 1 for crossdocking to Sales or Internal Order.
1412 -- {{
1413 -- Test for MOL qty = available to detail qty. MOL record should be
1414 -- crossdocked properly. }}11
1415 BEGIN
1416 UPDATE mtl_txn_request_lines SET
1417 backorder_delivery_detail_id = l_backorder_detail_id,
1418 crossdock_type = l_crossdock_type,
1419 wip_entity_id = l_wip_entity_id,
1420 repetitive_schedule_id = l_repetitive_schedule_id,
1421 operation_seq_num = l_operation_seq_num,
1422 wip_supply_type = l_wip_supply_type
1423 WHERE line_id = l_mol_line_id;
1424 EXCEPTION
1425 WHEN OTHERS THEN
1426 IF (l_debug = 1) THEN
1427 print_debug(p_log_prefix || 'Error updating the MOL record');
1428 END IF;
1429 -- Raise an exception. The caller will do the rollback, cleanups,
1430 -- and decide where to goto next.
1431 x_error_code := 'DB';
1432 RAISE FND_API.G_EXC_ERROR;
1433 END;
1434
1435 -- Update the MOL qty field to indicate how much quantity from the original MOL
1436 -- is still available for crossdocking.
1437 l_mol_qty := 0;
1438 l_mol_prim_qty := 0;
1439 l_mol_qty2 := 0;
1440 -- Do the following logic only for Opportunistic Crossdocking.
1441 -- This is needed so we can tell if the MOL supply line has been fully
1442 -- crossdocked yet.
1443 IF (p_crossdock_type = G_CRT_TYPE_OPP) THEN
1444 l_supply_atr_qty := 0;
1445 END IF;
1446
1447 IF (l_debug = 1) THEN
1448 print_debug(p_log_prefix || 'Successfully updated and crossdocked the MOL record');
1449 END IF;
1450 l_progress := '30';
1451 END IF; -- End crossdocking MOL record: Matches 'IF (l_mol_qty > l_atd_qty) THEN'
1452
1453 -- If the MOL used to crossdock was split, then it is the split MOL that should be
1454 -- tied to the WDD lines. We need to make sure crossdocked WDD lines are updated
1455 -- properly. Additionally, for Planned Crossdocking, the records in p_wsh_release_table
1456 -- also need to reflect the correct MOL pegged to the WDD. This needs to be done only
1457 -- for OE demand. For WIP backordered component demand, nothing needs to be done since
1458 -- the WIP job is not tied to the move order line (currently).
1459 -- For Opportunistic Crossdocking with WIP as the supply being crossdocked to a WDD demand,
1460 -- we do not need to update the move_order_line_id column. This is to mimic 11.5.10
1461 -- and prior behavior.
1462 IF (l_split_mol_line_id IS NOT NULL AND l_demand_type_id <> 5 AND l_supply_type_id <> 5) THEN
1463 -- Update the crossdocked WDD to point to the split MOL
1464 l_detail_info_tab(l_xdocked_wdd_index).move_order_line_id := l_split_mol_line_id;
1465
1466 -- Update the WDD record in the release table for Planned Crossdocking
1467 IF (p_crossdock_type = G_CRT_TYPE_PLAN) THEN
1468 IF (l_split_wdd_index IS NOT NULL) THEN
1469 -- WDD record was also split so update the appropriate crossdocked WDD
1470 p_wsh_release_table(l_split_wdd_index).move_order_line_id := l_split_mol_line_id;
1471 ELSE
1472 -- WDD record was not split so update the current WDD
1473 p_wsh_release_table(l_wdd_index).move_order_line_id := l_split_mol_line_id;
1474 END IF;
1475 END IF;
1476 IF (l_debug = 1) THEN
1477 print_debug(p_log_prefix || 'Successfully updated the WDD records with the split MOL line');
1478 END IF;
1479 l_progress := '40';
1480 END IF; -- End of logic to update WDD records with split MOL line
1481 x_new_mol_id := l_split_mol_line_id;
1482 EXCEPTION
1483 WHEN OTHERS THEN
1484 x_return_status := fnd_api.g_ret_sts_error;
1485 fnd_msg_pub.count_and_get(p_count => x_msg_count,
1486 p_data => x_msg_data);
1487 IF (l_debug = 1) THEN
1488 print_debug(p_log_prefix || 'Exiting Crossdock_MOL - Execution error: ' ||
1489 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
1490 END IF;
1491
1492 END Crossdock_MOL;
1493 -- {{ }}
1494 -- {{******************** End Crossdock_MOL ********************}}
1495 -- {{ }}
1496
1497
1498 -- This is a private procedure used to create a crossdock reservation during pegging.
1499 -- This will be used for both Planned and Opportunistic crossdocking.
1500 -- {{ }}
1501 -- {{******************** Procedure Create_RSV ********************}}
1502 PROCEDURE Create_RSV
1503 (p_log_prefix IN VARCHAR2,
1504 p_crossdock_type IN NUMBER,
1505 l_debug IN OUT NOCOPY NUMBER,
1506 l_organization_id IN OUT NOCOPY NUMBER,
1507 l_inventory_item_id IN OUT NOCOPY NUMBER,
1508 l_demand_type_id IN OUT NOCOPY NUMBER,
1509 l_demand_so_header_id IN OUT NOCOPY NUMBER,
1510 l_demand_line_id IN OUT NOCOPY NUMBER,
1511 l_split_wdd_id IN OUT NOCOPY NUMBER,
1512 l_primary_uom_code IN OUT NOCOPY VARCHAR2,
1513 l_demand_uom_code2 IN OUT NOCOPY VARCHAR2,
1514 l_supply_uom_code IN OUT NOCOPY VARCHAR2,
1515 l_atd_qty IN OUT NOCOPY NUMBER,
1516 l_atd_prim_qty IN OUT NOCOPY NUMBER,
1517 l_atd_wdd_qty2 IN OUT NOCOPY NUMBER,
1518 l_supply_type_id IN OUT NOCOPY NUMBER,
1519 l_supply_header_id IN OUT NOCOPY NUMBER,
1520 l_supply_line_id IN OUT NOCOPY NUMBER,
1521 l_supply_line_detail_id IN OUT NOCOPY NUMBER,
1522 l_crossdock_criteria_id IN OUT NOCOPY NUMBER,
1523 l_supply_expected_time IN OUT NOCOPY DATE,
1524 l_demand_expected_time IN OUT NOCOPY DATE,
1525 l_demand_project_id IN OUT NOCOPY NUMBER,
1526 l_demand_task_id IN OUT NOCOPY NUMBER,
1527 l_original_rsv_rec IN OUT NOCOPY inv_reservation_global.mtl_reservation_rec_type,
1528 l_original_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
1529 l_to_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
1530 l_quantity_reserved IN OUT NOCOPY NUMBER,
1531 l_quantity_reserved2 IN OUT NOCOPY NUMBER,
1532 l_rsv_id IN OUT NOCOPY NUMBER,
1533 x_return_status IN OUT NOCOPY VARCHAR2,
1534 x_msg_count IN OUT NOCOPY NUMBER,
1535 x_msg_data IN OUT NOCOPY VARCHAR2)
1536 IS
1537 l_progress VARCHAR2(10);
1538
1539 BEGIN
1540 -- {{
1541 -- Test that a valid crossdocked reservation is created. The quantities should
1542 -- match the relevant WDD and MOL records. }}
1543 --
1544 -- Set the values for the reservation record to be created
1545 IF (l_debug = 1) THEN
1546 print_debug(p_log_prefix || 'Requirement Date: ' || l_demand_expected_time);
1547 END IF;
1548 l_original_rsv_rec.reservation_id := NULL;
1549 l_original_rsv_rec.requirement_date := l_demand_expected_time;
1550 l_original_rsv_rec.organization_id := l_organization_id;
1551 l_original_rsv_rec.inventory_item_id := l_inventory_item_id;
1552 l_original_rsv_rec.demand_source_name := NULL;
1553 l_original_rsv_rec.demand_source_type_id := l_demand_type_id;
1554 l_original_rsv_rec.demand_source_header_id := l_demand_so_header_id;
1555 l_original_rsv_rec.demand_source_line_id := l_demand_line_id;
1556 l_original_rsv_rec.orig_demand_source_type_id := l_demand_type_id;
1557 l_original_rsv_rec.orig_demand_source_header_id := l_demand_so_header_id;
1558 l_original_rsv_rec.orig_demand_source_line_id := l_demand_line_id;
1559 -- For WIP as supply reservations, just create a regular non-crossdocked reservation.
1560 -- Do not stamp the WDD ID for the demand line detail.
1561 IF (l_supply_type_id = 5) THEN
1562 l_original_rsv_rec.demand_source_line_detail := NULL;
1563 l_original_rsv_rec.orig_demand_source_line_detail := NULL;
1564 ELSE
1565 l_original_rsv_rec.demand_source_line_detail := l_split_wdd_id;
1566 l_original_rsv_rec.orig_demand_source_line_detail := l_split_wdd_id;
1567 END IF;
1568 l_original_rsv_rec.demand_source_delivery := NULL;
1569 l_original_rsv_rec.primary_uom_code := l_primary_uom_code;
1570 l_original_rsv_rec.primary_uom_id := NULL;
1571 l_original_rsv_rec.secondary_uom_code := l_demand_uom_code2;
1572 l_original_rsv_rec.secondary_uom_id := NULL;
1573 l_original_rsv_rec.reservation_uom_code := l_supply_uom_code;
1574 l_original_rsv_rec.reservation_uom_id := NULL;
1575 l_original_rsv_rec.reservation_quantity := l_atd_qty;
1576 l_original_rsv_rec.primary_reservation_quantity := l_atd_prim_qty;
1577 l_original_rsv_rec.secondary_reservation_quantity := l_atd_wdd_qty2;
1578 l_original_rsv_rec.detailed_quantity := NULL;
1579 l_original_rsv_rec.secondary_detailed_quantity := NULL;
1580 l_original_rsv_rec.autodetail_group_id := NULL;
1581 l_original_rsv_rec.external_source_code := 'XDOCK';
1582 l_original_rsv_rec.external_source_line_id := NULL;
1583 l_original_rsv_rec.supply_source_type_id := l_supply_type_id;
1584 l_original_rsv_rec.orig_supply_source_type_id := l_supply_type_id;
1585 l_original_rsv_rec.supply_source_name := NULL;
1586 -- Since reservations with supply type of Receiving are not at the
1587 -- MO header and line level, these fields should be NULL.
1588 IF (l_supply_type_id = 27) THEN
1589 l_original_rsv_rec.supply_source_header_id := NULL;
1590 l_original_rsv_rec.supply_source_line_id := NULL;
1591 l_original_rsv_rec.supply_source_line_detail := NULL;
1592 l_original_rsv_rec.orig_supply_source_header_id := NULL;
1593 l_original_rsv_rec.orig_supply_source_line_id := NULL;
1594 l_original_rsv_rec.orig_supply_source_line_detail := NULL;
1595 ELSIF (l_supply_type_id = 7) THEN
1596 -- Reservations with supply type of Internal Req should have a NULL
1597 -- value for the supply source line detail. Right now this field could
1598 -- potentially store the shipment line ID for an Internal Req that has quantity
1599 -- shipped. Reservations currently are not created at this level of detail.
1600 l_original_rsv_rec.supply_source_header_id := l_supply_header_id;
1601 l_original_rsv_rec.supply_source_line_id := l_supply_line_id;
1602 l_original_rsv_rec.supply_source_line_detail := NULL;
1603 l_original_rsv_rec.orig_supply_source_header_id := l_supply_header_id;
1604 l_original_rsv_rec.orig_supply_source_line_id := l_supply_line_id;
1605 l_original_rsv_rec.orig_supply_source_line_detail := NULL;
1606 ELSIF (l_supply_type_id = 5) THEN
1607 -- Reservations with supply type of WIP should just have the WIP entity ID
1608 -- stored as the supply source header ID. The other WIP fields such as
1609 -- operation seq num and repetitive schedule ID are not currently stored
1610 -- on the reservation.
1611 l_original_rsv_rec.supply_source_header_id := l_supply_header_id;
1612 l_original_rsv_rec.supply_source_line_id := NULL;
1613 l_original_rsv_rec.supply_source_line_detail := NULL;
1614 l_original_rsv_rec.orig_supply_source_header_id := l_supply_header_id;
1615 l_original_rsv_rec.orig_supply_source_line_id := NULL;
1616 l_original_rsv_rec.orig_supply_source_line_detail := NULL;
1617 ELSE
1618 l_original_rsv_rec.supply_source_header_id := l_supply_header_id;
1619 l_original_rsv_rec.supply_source_line_id := l_supply_line_id;
1620 l_original_rsv_rec.supply_source_line_detail := l_supply_line_detail_id;
1621 l_original_rsv_rec.orig_supply_source_header_id := l_supply_header_id;
1622 l_original_rsv_rec.orig_supply_source_line_id := l_supply_line_id;
1623 l_original_rsv_rec.orig_supply_source_line_detail := l_supply_line_detail_id;
1624 END IF;
1625 l_original_rsv_rec.revision := NULL;
1626 l_original_rsv_rec.subinventory_code := NULL;
1627 l_original_rsv_rec.subinventory_id := NULL;
1628 l_original_rsv_rec.locator_id := NULL;
1629 l_original_rsv_rec.lot_number := NULL;
1630 l_original_rsv_rec.lot_number_id := NULL;
1631 l_original_rsv_rec.pick_slip_number := NULL;
1632 l_original_rsv_rec.lpn_id := NULL;
1633 l_original_rsv_rec.attribute_category := NULL;
1634 l_original_rsv_rec.attribute1 := NULL;
1635 l_original_rsv_rec.attribute2 := NULL;
1636 l_original_rsv_rec.attribute3 := NULL;
1637 l_original_rsv_rec.attribute4 := NULL;
1638 l_original_rsv_rec.attribute5 := NULL;
1639 l_original_rsv_rec.attribute6 := NULL;
1640 l_original_rsv_rec.attribute7 := NULL;
1641 l_original_rsv_rec.attribute8 := NULL;
1642 l_original_rsv_rec.attribute9 := NULL;
1643 l_original_rsv_rec.attribute10 := NULL;
1644 l_original_rsv_rec.attribute11 := NULL;
1645 l_original_rsv_rec.attribute12 := NULL;
1646 l_original_rsv_rec.attribute13 := NULL;
1647 l_original_rsv_rec.attribute14 := NULL;
1648 l_original_rsv_rec.attribute15 := NULL;
1649 l_original_rsv_rec.ship_ready_flag := NULL;
1650 l_original_rsv_rec.staged_flag := NULL;
1651 -- For WIP as supply reservations, just create a regular non-crossdocked reservation.
1652 IF (l_supply_type_id = 5) THEN
1653 l_original_rsv_rec.crossdock_flag := NULL;
1654 l_original_rsv_rec.crossdock_criteria_id := NULL;
1655 ELSE
1656 l_original_rsv_rec.crossdock_flag := 'Y';
1657 l_original_rsv_rec.crossdock_criteria_id := l_crossdock_criteria_id;
1658 END IF;
1659 l_original_rsv_rec.serial_reservation_quantity := NULL;
1660 l_original_rsv_rec.supply_receipt_date := l_supply_expected_time;
1661 l_original_rsv_rec.demand_ship_date := l_demand_expected_time;
1662 l_original_rsv_rec.project_id := l_demand_project_id;
1663 l_original_rsv_rec.task_id := l_demand_task_id;
1664 l_original_rsv_rec.serial_number := NULL;
1665 l_progress := '10';
1666
1667 IF (l_debug = 1) THEN
1668 print_debug(p_log_prefix || 'Call the create_reservation API to create the crossdock peg');
1669 END IF;
1670 INV_RESERVATION_PVT.create_reservation
1671 (p_api_version_number => 1.0,
1672 p_init_msg_lst => fnd_api.g_false,
1673 x_return_status => x_return_status,
1674 x_msg_count => x_msg_count,
1675 x_msg_data => x_msg_data,
1676 p_rsv_rec => l_original_rsv_rec,
1677 p_serial_number => l_original_serial_number,
1678 x_serial_number => l_to_serial_number,
1679 p_partial_reservation_flag => fnd_api.g_false,
1680 p_force_reservation_flag => fnd_api.g_false,
1681 p_validation_flag => fnd_api.g_true,
1682 x_quantity_reserved => l_quantity_reserved,
1683 x_secondary_quantity_reserved => l_quantity_reserved2,
1684 x_reservation_id => l_rsv_id
1685 );
1686
1687 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1688 IF (l_debug = 1) THEN
1689 print_debug(p_log_prefix || 'Error returned from create_reservation API: '
1690 || x_return_status);
1691 END IF;
1692 -- Raise an exception. The caller will do the rollback, cleanups,
1693 -- and decide where to goto next.
1694 RAISE FND_API.G_EXC_ERROR;
1695 END IF;
1696 l_progress := '20';
1697
1698 EXCEPTION
1699 WHEN OTHERS THEN
1700 x_return_status := fnd_api.g_ret_sts_error;
1701 fnd_msg_pub.count_and_get(p_count => x_msg_count,
1702 p_data => x_msg_data);
1703 IF (l_debug = 1) THEN
1704 print_debug(p_log_prefix || 'Exiting Create_RSV - Execution error: ' ||
1705 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
1706 END IF;
1707
1708 END Create_RSV;
1709 -- {{ }}
1710 -- {{******************** End Create_RSV ********************}}
1711 -- {{ }}
1712
1713
1714 -- {{ }}
1715 -- {{******************** Procedure Planned_Cross_Dock ********************}}
1716 PROCEDURE Planned_Cross_Dock
1717 (p_api_version IN NUMBER,
1718 p_init_msg_list IN VARCHAR2,
1719 p_commit IN VARCHAR2,
1720 x_return_status OUT NOCOPY VARCHAR2,
1721 x_msg_count OUT NOCOPY NUMBER,
1722 x_msg_data OUT NOCOPY VARCHAR2,
1723 p_batch_id IN NUMBER,
1724 p_wsh_release_table IN OUT NOCOPY WSH_PR_CRITERIA.relRecTabTyp,
1725 p_trolin_delivery_ids IN OUT NOCOPY WSH_UTIL_CORE.Id_Tab_Type,
1726 p_del_detail_id IN OUT NOCOPY WSH_PICK_LIST.DelDetTabTyp,
1727 p_simulation_mode in varchar2 default 'N')
1728 IS
1729 l_api_name CONSTANT VARCHAR2(30) := 'Planned_Cross_Dock';
1730 l_api_version CONSTANT NUMBER := 1.0;
1731 l_progress VARCHAR2(10);
1732 l_debug NUMBER := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
1733
1734 -- This variable is used to indicate if the custom APIs were used.
1735 l_api_is_implemented BOOLEAN;
1736
1737 -- These variable will store the org, allocation method, crossdock criteria ID
1738 -- and the existing reservations only flag for the inputted picking batch.
1739 l_organization_id NUMBER;
1740 l_allocation_method VARCHAR2(1);
1741 l_wpb_xdock_criteria_id NUMBER;
1742 l_existing_rsvs_only VARCHAR2(1);
1743
1744 -- This variable stores the PJM org parameter to allow cross project allocation
1745 -- when matching supply to demand lines for crossdocking. Possible values are 'Y' or 'N'.
1746 l_allow_cross_proj_issues VARCHAR2(1);
1747
1748 -- This variable indicates if the org is PJM enabled or not. 1 = Yes, 2 = No
1749 l_project_ref_enabled NUMBER;
1750
1751 -- This boolean variable indicates if the org is a WMS org or not.
1752 l_wms_org_flag BOOLEAN;
1753
1754 -- This variable stores the current item being crossdocking from the release table
1755 l_inventory_item_id NUMBER;
1756 l_primary_uom_code VARCHAR2(3);
1757
1758 -- Cursor to retrieve valid approved PO supply lines
1759 CURSOR po_approved_lines IS
1760 SELECT
1761 poll.po_header_id AS header_id,
1762 poll.line_location_id AS line_id,
1763 NULL AS line_detail_id,
1764 NULL AS quantity,
1765 muom.uom_code AS uom_code,
1766 NULL AS primary_quantity,
1767 NULL AS secondary_quantity,
1768 NULL AS secondary_uom_code,
1769 MIN(pod.project_id) AS project_id,
1770 MIN(pod.task_id) AS task_id,
1771 NULL AS lpn_id
1772 FROM po_headers_all poh, po_lines_all pol, po_line_locations_all poll,
1773 po_distributions_all pod, po_line_types plt, mtl_units_of_measure muom
1774 WHERE poh.type_lookup_code IN ('STANDARD','PLANNED','BLANKET','CONTRACT')
1775 AND NVL(poh.cancel_flag, 'N') IN ('N', 'I')
1776 AND NVL(poh.closed_code, 'OPEN') NOT IN ('FINALLY CLOSED','CLOSED FOR RECEIVING','CLOSED')
1777 AND pol.po_header_id = poh.po_header_id
1778 AND poh.po_header_id = poll.po_header_id
1779 AND pol.po_line_id = poll.po_line_id
1780 AND pod.po_header_id = poh.po_header_id
1781 AND pod.po_line_id = pol.po_line_id
1782 AND pod.line_location_id = poll.line_location_id
1783 AND pol.item_id = l_inventory_item_id
1784 AND pol.line_type_id = plt.line_type_id
1785 AND NVL(plt.outside_operation_flag, 'N') = 'N'
1786 AND poll.unit_meas_lookup_code = muom.unit_of_measure
1787 AND NVL(poll.approved_flag, 'N') = 'Y'
1788 AND NVL(poll.cancel_flag, 'N') = 'N'
1789 AND NVL(poll.closed_code, 'OPEN') NOT IN ('FINALLY CLOSED','CLOSED FOR RECEIVING','CLOSED')
1790 AND poll.shipment_type IN ('STANDARD', 'BLANKET', 'SCHEDULED')
1791 AND poll.ship_to_organization_id = l_organization_id
1792 AND poll.quantity > NVL(poll.quantity_received, 0)
1793 AND NVL(poll.receiving_routing_id,
1794 WMS_Xdock_Pegging_Pub.get_default_routing_id(l_organization_id,
1795 l_inventory_item_id,
1796 poh.vendor_id)) <> 3
1797 AND NOT EXISTS (SELECT 'Invalid Destination'
1798 FROM po_distributions_all pod2
1799 WHERE pod2.po_header_id = poll.po_header_id
1800 AND pod2.po_line_id = poll.po_line_id
1801 AND pod2.line_location_id = poll.line_location_id
1802 AND NVL(pod2.destination_type_code, pod2.destination_context) IN
1803 ('EXPENSE','SHOP FLOOR'))
1804 AND NOT EXISTS (SELECT 'Drop Ship'
1805 FROM oe_drop_ship_sources odss
1806 WHERE odss.po_header_id = poll.po_header_id
1807 AND odss.po_line_id = poll.po_line_id
1808 AND odss.line_location_id = poll.line_location_id)
1809 GROUP BY poll.po_header_id, poll.po_line_id, poll.line_location_id, muom.uom_code
1810 HAVING COUNT(DISTINCT NVL(pod.project_id, -999)) = 1
1811 AND COUNT(DISTINCT NVL(pod.task_id, -999)) = 1;
1812
1813
1814 -- Cursor to retrieve valid ASN supply lines
1815 CURSOR po_asn_lines IS
1816 SELECT
1817 rsl.po_header_id AS header_id,
1818 rsl.po_line_location_id AS line_id,
1819 rsl.shipment_line_id AS line_detail_id,
1820 NULL AS quantity,
1821 muom.uom_code AS uom_code,
1822 NULL AS primary_quantity,
1823 NULL AS secondary_quantity,
1824 NULL AS secondary_uom_code,
1825 MIN(pod.project_id) AS project_id,
1826 MIN(pod.task_id) AS task_id,
1827 NULL AS lpn_id
1828 FROM rcv_shipment_headers rsh, rcv_shipment_lines rsl, po_lines_all pol, po_line_types plt,
1829 po_line_locations_all poll, po_distributions_all pod, mtl_units_of_measure muom
1830 WHERE rsh.shipment_num IS NOT NULL
1831 AND rsh.receipt_source_code = 'VENDOR'
1832 AND rsh.asn_type in ('ASN','ASBN')
1833 AND rsh.shipment_header_id = rsl.shipment_header_id
1834 AND rsl.to_organization_id = l_organization_id
1835 AND rsl.shipment_line_status_code in ('EXPECTED','PARTIALLY RECEIVED')
1836 AND rsl.item_id = l_inventory_item_id
1837 AND rsl.quantity_shipped > NVL(rsl.quantity_received, 0)
1838 AND rsl.po_line_id = pol.po_line_id
1839 AND pol.line_type_id = plt.line_type_id
1840 AND NVL(plt.outside_operation_flag, 'N') = 'N'
1841 AND pol.po_line_id = poll.po_line_id
1842 AND rsl.po_line_location_id = poll.line_location_id
1843 AND pod.po_line_id = pol.po_line_id
1844 AND pod.line_location_id = poll.line_location_id
1845 AND rsl.unit_of_measure = muom.unit_of_measure
1846 AND NVL(poll.receiving_routing_id,
1847 WMS_Xdock_Pegging_Pub.get_default_routing_id(l_organization_id,
1848 l_inventory_item_id,
1849 rsh.vendor_id)) <> 3
1850 AND NOT EXISTS (SELECT 'Invalid Destination'
1851 FROM po_distributions_all pod2
1852 WHERE pod2.po_header_id = poll.po_header_id
1853 AND pod2.po_line_id = poll.po_line_id
1854 AND pod2.line_location_id = poll.line_location_id
1855 AND NVL(pod2.destination_type_code, pod2.destination_context) IN
1856 ('EXPENSE','SHOP FLOOR'))
1857 AND NOT EXISTS (SELECT 'Drop Ship'
1858 FROM oe_drop_ship_sources odss
1859 WHERE odss.po_header_id = poll.po_header_id
1860 AND odss.po_line_id = poll.po_line_id
1861 AND odss.line_location_id = poll.line_location_id)
1862 GROUP BY rsl.po_header_id, rsl.po_line_location_id, rsl.shipment_line_id,
1863 muom.uom_code
1864 HAVING COUNT(DISTINCT NVL(pod.project_id, -999)) = 1
1865 AND COUNT(DISTINCT NVL(pod.task_id, -999)) = 1;
1866
1867
1868 -- Cursor to retrieve valid Internal Requisition supply lines
1869 CURSOR internal_req_lines IS
1870 -- Shipped In Transit Internal Reqs
1871 SELECT
1872 prl.requisition_header_id AS header_id,
1873 prl.requisition_line_id AS line_id,
1874 rsl.shipment_line_id AS line_detail_id,
1875 NULL AS quantity,
1876 muom.uom_code AS uom_code,
1877 NULL AS primary_quantity,
1878 NULL AS secondary_quantity,
1879 NULL AS secondary_uom_code,
1880 MIN(prd.project_id) AS project_id,
1881 MIN(prd.task_id) AS task_id,
1882 NULL AS lpn_id
1883 FROM po_requisition_headers_all prh, po_requisition_lines_all prl,
1884 rcv_shipment_lines rsl, rcv_shipment_headers rsh, po_req_distributions_all prd,
1885 mtl_units_of_measure muom
1886 WHERE prh.requisition_header_id = prl.requisition_header_id
1887 AND prd.requisition_line_id = prl.requisition_line_id
1888 AND prh.authorization_status = 'APPROVED'
1889 AND NVL(prl.cancel_flag,'N') = 'N'
1890 AND prl.source_type_code = 'INVENTORY'
1891 AND prl.destination_organization_id = l_organization_id
1892 AND prl.item_id = l_inventory_item_id
1893 AND rsl.requisition_line_id = prl.requisition_line_id
1894 AND rsl.routing_header_id > 0
1895 AND rsl.shipment_line_status_code IN ('EXPECTED','PARTIALLY RECEIVED')
1896 AND rsl.to_organization_id = l_organization_id
1897 AND rsl.item_id = l_inventory_item_id
1898 AND rsl.quantity_shipped > NVL(rsl.quantity_received, 0)
1899 AND rsh.shipment_header_id = rsl.shipment_header_id
1900 AND rsl.unit_of_measure = muom.unit_of_measure
1901 AND NVL(rsl.routing_header_id,
1902 WMS_Xdock_Pegging_Pub.get_default_routing_id(l_organization_id,
1903 l_inventory_item_id,
1904 rsh.vendor_id)) <> 3
1905 AND NVL(NVL(prl.destination_type_code, prl.destination_context), 'INVENTORY') NOT IN
1906 ('EXPENSE', 'SHOP FLOOR')
1907 GROUP BY prl.requisition_header_id, prl.requisition_line_id, rsl.shipment_line_id,
1908 muom.uom_code
1909 HAVING COUNT(DISTINCT NVL(prd.project_id, -999)) = 1
1910 AND COUNT(DISTINCT NVL(prd.task_id, -999)) = 1
1911
1912 UNION
1913 -- Approved but not shipped Internal Reqs
1914 SELECT
1915 prl.requisition_header_id AS header_id,
1916 prl.requisition_line_id AS line_id,
1917 NULL AS line_detail_id,
1918 NULL AS quantity,
1919 muom.uom_code AS uom_code,
1920 NULL AS primary_quantity,
1921 NULL AS secondary_quantity,
1922 NULL AS secondary_uom_code,
1923 MIN(prd.project_id) AS project_id,
1924 MIN(prd.task_id) AS task_id,
1925 NULL AS lpn_id
1926 FROM po_requisition_headers_all prh, po_requisition_lines_all prl,
1927 po_req_distributions_all prd, mtl_interorg_parameters mip, mtl_units_of_measure muom
1928 WHERE prh.requisition_header_id = prl.requisition_header_id
1929 AND prd.requisition_line_id = prl.requisition_line_id
1930 AND prh.authorization_status = 'APPROVED'
1931 AND NVL(prl.cancel_flag,'N') = 'N'
1932 AND prl.source_type_code = 'INVENTORY'
1933 AND prl.destination_organization_id = l_organization_id
1934 AND prl.item_id = l_inventory_item_id
1935 AND NOT EXISTS (SELECT 'Ship Confirmed'
1936 FROM rcv_shipment_lines rsl
1937 WHERE rsl.requisition_line_id = prl.requisition_line_id
1938 AND rsl.routing_header_id > 0
1939 AND rsl.shipment_line_status_code <> 'CANCELLED'
1940 AND rsl.to_organization_id = l_organization_id
1941 AND rsl.item_id = l_inventory_item_id)
1942 AND mip.from_organization_id = prl.source_organization_id
1943 AND mip.to_organization_id = prl.destination_organization_id
1944 AND prl.unit_meas_lookup_code = muom.unit_of_measure
1945 AND NVL(mip.routing_header_id,
1946 WMS_Xdock_Pegging_Pub.get_default_routing_id(l_organization_id,
1947 l_inventory_item_id,
1948 prl.vendor_id)) <> 3
1949 AND NVL(NVL(prl.destination_type_code, prl.destination_context), 'INVENTORY') NOT IN
1950 ('EXPENSE', 'SHOP FLOOR')
1951 GROUP BY prl.requisition_header_id, prl.requisition_line_id, muom.uom_code
1952 HAVING COUNT(DISTINCT NVL(prd.project_id, -999)) = 1
1953 AND COUNT(DISTINCT NVL(prd.task_id, -999)) = 1;
1954
1955
1956 -- Cursor to retrieve valid In Transit Shipment supply lines
1957 CURSOR intship_lines IS
1958 SELECT
1959 rsl.shipment_header_id AS header_id,
1960 rsl.shipment_line_id AS line_id,
1961 NULL AS line_detail_id,
1962 NULL AS quantity,
1963 muom.uom_code AS uom_code,
1964 NULL AS primary_quantity,
1965 NULL AS secondary_quantity,
1966 NULL AS secondary_uom_code,
1967 NULL AS project_id,
1968 NULL AS task_id,
1969 NULL AS lpn_id
1970 FROM rcv_shipment_headers rsh, rcv_shipment_lines rsl, mtl_units_of_measure muom
1971 WHERE rsh.shipment_num IS NOT NULL
1972 AND rsh.shipment_header_id = rsl.shipment_header_id
1973 AND rsh.receipt_source_code = 'INVENTORY'
1974 AND EXISTS (SELECT 'Available Supply'
1975 FROM mtl_supply ms
1976 WHERE ms.to_organization_id = l_organization_id
1977 AND ms.shipment_header_id = rsh.shipment_header_id)
1978 AND rsl.shipment_line_status_code IN ('EXPECTED','PARTIALLY RECEIVED')
1979 AND rsl.to_organization_id = l_organization_id
1980 AND rsl.item_id = l_inventory_item_id
1981 AND rsl.quantity_shipped > NVL(rsl.quantity_received, 0)
1982 AND rsl.unit_of_measure = muom.unit_of_measure
1983 AND NVL(rsl.routing_header_id,
1984 WMS_Xdock_Pegging_Pub.get_default_routing_id(l_organization_id,
1985 l_inventory_item_id,
1986 rsh.vendor_id)) <> 3
1987 AND NVL(NVL(rsl.destination_type_code, rsl.destination_context), 'INVENTORY') NOT IN
1988 ('EXPENSE','SHOP FLOOR');
1989 --AND (l_project_ref_enabled = 2 OR l_allow_cross_proj_issues = 'Y');
1990 -- In Transit Shipments going to a destination org that is PJM enabled will
1991 -- always have a NULL project/task, i.e. part of common stock. The assumption is
1992 -- that if such a supply exists, the user cannot receive it into a specific project/task.
1993
1994
1995 -- Cursor to retrieve valid In Receiving supply lines.
1996 CURSOR in_receiving_lines IS
1997 SELECT
1998 mtrl.header_id AS header_id,
1999 mtrl.line_id AS line_id,
2000 NULL AS line_detail_id,
2001 mtrl.quantity AS quantity,
2002 mtrl.uom_code AS uom_code,
2003 mtrl.primary_quantity AS primary_quantity,
2004 mtrl.secondary_quantity AS secondary_quantity,
2005 mtrl.secondary_uom_code AS secondary_uom_code,
2006 mtrl.project_id AS project_id,
2007 mtrl.task_id AS task_id,
2008 mtrl.lpn_id AS lpn_id
2009 FROM mtl_txn_request_lines mtrl, mtl_txn_request_headers mtrh,
2010 wms_license_plate_numbers wlpn
2011 WHERE mtrl.header_id = mtrh.header_id
2012 AND mtrh.move_order_type = inv_globals.g_move_order_put_away
2013 AND mtrl.organization_id = l_organization_id
2014 AND mtrl.inventory_item_id = l_inventory_item_id
2015 -- Modified the line below to use an IN instead of <> so the
2016 -- index MTL_TXN_REQUEST_LINES_N10 on MTRL is more likely to be used.
2017 -- AND mtrl.line_status <> inv_globals.g_to_status_closed
2018 AND mtrl.line_status IN (inv_globals.g_to_status_preapproved,
2019 inv_globals.g_to_status_approved)
2020 AND mtrl.backorder_delivery_detail_id IS NULL
2021 AND mtrl.lpn_id IS NOT NULL
2022 AND mtrl.quantity > 0
2023 AND NVL(mtrl.quantity_delivered, 0) = 0
2024 AND NVL(mtrl.quantity_detailed, 0) = 0
2025 AND NVL(mtrl.inspection_status, 2) = 2
2026 AND NVL(mtrl.wms_process_flag, 1) = 1
2027 AND NVL(mtrl.reference, 'non-RMA') <> 'ORDER_LINE_ID'
2028 AND mtrl.lpn_id = wlpn.lpn_id
2029 AND wlpn.lpn_context = 3
2030 -- Added the following line so the index: WMS_LICENSE_PLATE_NUMBERS_N6
2031 -- can be used in case the SQL optimizer uses WLPN as the driving table.
2032 AND wlpn.organization_id = l_organization_id;
2033
2034
2035 -- Variables to retrieve the values from the supply lines cursors.
2036 -- We will bulk collect the records from the cursors into these PLSQL tables and
2037 -- use them to do a bulk insert into the xdock pegging global temp table.
2038 TYPE num_tab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
2039 TYPE uom_tab IS TABLE OF VARCHAR2(3) INDEX BY BINARY_INTEGER;
2040 l_header_id_tb num_tab;
2041 l_line_id_tb num_tab;
2042 l_line_detail_id_tb num_tab;
2043 l_uom_code_tb uom_tab;
2044 l_project_id_tb num_tab;
2045 l_task_id_tb num_tab;
2046
2047 -- Additional PLSQL tables used only by In Receiving supply source type.
2048 -- Since In Receiving supply lines consist of MOLs which can be split during
2049 -- crossdocking, we need this information in order to properly split the MOL records.
2050 -- Non-receiving supply types will just select NULL values for them currently.
2051 l_quantity_tb num_tab;
2052 l_primary_quantity_tb num_tab;
2053 l_secondary_quantity_tb num_tab;
2054 l_secondary_uom_code_tb uom_tab;
2055 l_lpn_id_tb num_tab;
2056
2057 -- Variables to store the expected time values for the supply line records retrieved.
2058 -- We will use the date tables to do a bulk insert into the xdock pegging global temp table.
2059 TYPE date_tab IS TABLE OF DATE INDEX BY BINARY_INTEGER;
2060 l_dock_start_time_tb date_tab;
2061 l_dock_mean_time_tb date_tab;
2062 l_dock_end_time_tb date_tab;
2063 l_expected_time_tb date_tab;
2064
2065 -- Type used to keep track of which supply source types for a given item
2066 -- have already been queried for so we do not do this again.
2067 -- This table will be indexed by the supply source code as used by the crossdock criteria
2068 -- tables. If an entry exists for that index it will have a value of TRUE. If the value
2069 -- does not exist, then the supply source type has not been queried for yet.
2070 TYPE bool_tab IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER;
2071
2072 -- Table indexed by inventory_item_id to keep track of which
2073 -- supply source types have already been retrieved and inserted into
2074 -- the wms_xdock_pegging_gtmp table.
2075 TYPE src_types_retrieved_tb IS TABLE OF bool_tab INDEX BY BINARY_INTEGER;
2076 l_src_types_retrieved_tb src_types_retrieved_tb;
2077
2078 -- Index used to loop through the release table
2079 l_wdd_index NUMBER;
2080
2081 -- Cursor to lock the WDD demand record
2082 CURSOR lock_wdd_record(p_delivery_detail_id NUMBER) IS
2083 SELECT delivery_detail_id
2084 FROM wsh_delivery_details
2085 WHERE delivery_detail_id = p_delivery_detail_id
2086 FOR UPDATE NOWAIT;
2087
2088 -- Variables used for the current WDD demand record
2089 l_demand_type_id NUMBER;
2090 l_demand_header_id NUMBER; -- OE order header ID
2091 l_demand_so_header_id NUMBER; -- Sales order header ID
2092 l_demand_line_id NUMBER;
2093 l_demand_line_detail_id NUMBER;
2094 l_crossdock_criteria_id NUMBER;
2095 l_dock_start_time DATE;
2096 l_dock_mean_time DATE;
2097 l_dock_end_time DATE;
2098 l_demand_expected_time DATE;
2099 l_demand_dock_exists BOOLEAN;
2100 l_demand_qty NUMBER;
2101 l_demand_uom_code VARCHAR2(3);
2102 l_demand_qty2 NUMBER;
2103 l_demand_uom_code2 VARCHAR2(3);
2104 l_demand_project_id NUMBER;
2105 l_demand_task_id NUMBER;
2106
2107 -- Type used to cache the item parameters needed
2108 TYPE item_params_rec IS RECORD
2109 (primary_uom_code VARCHAR2(3),
2110 reservable_type NUMBER,
2111 lot_control_code NUMBER,
2112 lot_divisible_flag VARCHAR2(1),
2113 item_type VARCHAR2(30)
2114 );
2115 -- Table indexed by inventory_item_id to store item parameters
2116 TYPE item_params_tb IS TABLE OF item_params_rec
2117 INDEX BY BINARY_INTEGER;
2118 l_item_params_tb item_params_tb;
2119
2120 -- Variables used to call the rules engine to retrieve the crossdock criteria
2121 l_return_type VARCHAR2(1);
2122 l_sequence_number NUMBER;
2123
2124 -- Type used to cache the UOM class info for a given UOM code
2125 TYPE uom_class_tb IS TABLE OF VARCHAR2(10) INDEX BY VARCHAR2(3);
2126 l_uom_class_tb uom_class_tb;
2127
2128 -- Cursor to retrieve the existing high level non-crossdocked non-inventory reservations
2129 -- for the current WDD record. For these types of reservations, the detailed_quantity
2130 -- column should be NULL or 0.
2131 -- We will also lock the reservations records here. Using the SKIP LOCKED keyword,
2132 -- we can select only row records which are lockable without erroring out the entire query.
2133 CURSOR existing_rsvs_cursor IS
2134 SELECT reservation_id, supply_source_type_id, supply_source_header_id,
2135 supply_source_line_id, supply_source_line_detail,
2136 reservation_quantity, reservation_uom_code,
2137 secondary_reservation_quantity, secondary_uom_code,
2138 primary_reservation_quantity, primary_uom_code
2139 FROM mtl_reservations
2140 WHERE organization_id = l_organization_id
2141 AND inventory_item_id = l_inventory_item_id
2142 AND demand_source_type_id = l_demand_type_id
2143 AND demand_source_line_id = l_demand_line_id
2144 AND supply_source_type_id <> inv_reservation_global.g_source_type_inv
2145 AND NVL(crossdock_flag, 'N') = 'N'
2146 AND primary_reservation_quantity - NVL(detailed_quantity, 0) > 0
2147 FOR UPDATE SKIP LOCKED; --Bug 6813492
2148
2149 -- Table to store the results from the existing reservations cursor
2150 TYPE existing_rsvs_tb IS TABLE OF existing_rsvs_cursor%ROWTYPE INDEX BY BINARY_INTEGER;
2151 l_existing_rsvs_tb existing_rsvs_tb;
2152
2153 -- Index used to loop through the existing high level non-inventory reservations
2154 l_rsv_index NUMBER;
2155
2156 -- Variables for existing reservations and the related supply line on it
2157 l_rsv_id NUMBER;
2158 l_rsv_qty NUMBER;
2159 l_rsv_uom_code VARCHAR2(3);
2160 l_rsv_qty2 NUMBER;
2161 l_rsv_uom_code2 VARCHAR2(3);
2162 l_rsv_prim_qty NUMBER;
2163 l_rsv_prim_uom_code VARCHAR2(3);
2164 l_supply_uom_code VARCHAR2(3);
2165 l_supply_type_id NUMBER;
2166 l_supply_header_id NUMBER;
2167 l_supply_line_id NUMBER;
2168 l_supply_line_detail_id NUMBER;
2169 l_supply_project_id NUMBER;
2170 l_supply_task_id NUMBER;
2171
2172 -- Variable used to store the current supply source code (as used by crossdock criteria)
2173 -- The supply source codes are different for Reservations and Crossdock Criteria.
2174 l_supply_src_code NUMBER;
2175
2176 -- Variable for retrieving the expected receipt time for supply line
2177 -- from existing reservations.
2178 l_supply_expected_time DATE;
2179 l_supply_dock_exists BOOLEAN;
2180
2181 -- Crossdock Criteria time interval values.
2182 -- The max precision for the DAY is 2 digits (i.e. 99 DAYs is the largest possible value)
2183 -- and will be enforced in the crossdock criteria definition form.
2184 l_xdock_window_interval INTERVAL DAY(2) TO SECOND;
2185 l_buffer_interval INTERVAL DAY(2) TO SECOND;
2186 l_processing_interval INTERVAL DAY(2) TO SECOND;
2187 l_past_due_interval INTERVAL DAY(2) TO SECOND;
2188 -- Store the past due time value too so we can tell in Get_Supply_Lines if this
2189 -- value is null or not.
2190 l_past_due_time NUMBER;
2191
2192 -- Crossdock time window start and end times. Any valid supplies within this
2193 -- time interval are valid for crossdocking.
2194 l_xdock_start_time DATE;
2195 l_xdock_end_time DATE;
2196
2197 -- The following are cursors used to satisfy existing reservations. The supply line(s)
2198 -- on the reservation needs to be locked before we can crossdock it.
2199 -- A UOM code to match can be inputted if we are trying to crossdock an existing
2200 -- reservation for this supply type. If the UOM Integrity flag is 'Y',
2201 -- we only want to pick up supply line(s) that have the same UOM as the reservation.
2202 -- We just need to lock the appropriate records (do not need to lock MUOM records).
2203 -- The project and task of the demand line is also passed in to match to the supply.
2204 -- If the org is PJM enabled and cross project allocation is not allowed, then the project
2205 -- and task values have to match. The project and task values for the PO, ASN, and Int Req
2206 -- cursors are retrieved from a subquery. This is because the FOR UPDATE OF clause does not
2207 -- work if there is a GROUP BY in the main clause.
2208
2209 -- Cursor to lock the PO supply line record.
2210 CURSOR lock_po_record(p_uom_code VARCHAR2, p_project_id NUMBER, p_task_id NUMBER) IS
2211 SELECT muom.uom_code, pod.project_id, pod.task_id
2212 FROM po_line_locations_all poll, mtl_units_of_measure muom,
2213 (SELECT po_header_id, po_line_id, line_location_id,
2214 MIN(project_id) AS project_id, MIN(task_id) AS task_id
2215 FROM po_distributions_all
2216 WHERE po_header_id = l_supply_header_id
2217 AND line_location_id = l_supply_line_id
2218 GROUP BY po_header_id, po_line_id, line_location_id
2219 HAVING COUNT(DISTINCT NVL(project_id, -999)) = 1
2220 AND COUNT(DISTINCT NVL(task_id, -999)) = 1
2221 AND (l_project_ref_enabled = 2 OR
2222 l_allow_cross_proj_issues = 'Y' OR
2223 (NVL(MIN(project_id), -999) = NVL(p_project_id, -999) AND
2224 NVL(MIN(task_id), -999) = NVL(p_task_id, -999)))) pod
2225 WHERE poll.po_header_id = l_supply_header_id
2226 AND poll.line_location_id = l_supply_line_id
2227 AND poll.unit_meas_lookup_code = muom.unit_of_measure
2228 AND (p_uom_code IS NULL OR muom.uom_code = p_uom_code)
2229 AND pod.po_header_id = poll.po_header_id
2230 AND pod.po_line_id = poll.po_line_id
2231 AND pod.line_location_id = poll.line_location_id
2232 FOR UPDATE OF poll.line_location_id NOWAIT;
2233
2234 -- Cursor to lock the ASN supply line record.
2235 CURSOR lock_asn_record(p_uom_code VARCHAR2, p_project_id NUMBER, p_task_id NUMBER) IS
2236 SELECT muom.uom_code, pod.project_id, pod.task_id
2237 FROM rcv_shipment_lines rsl, po_line_locations_all poll, mtl_units_of_measure muom,
2238 (SELECT po_header_id, po_line_id, line_location_id,
2239 MIN(project_id) AS project_id, MIN(task_id) AS task_id
2240 FROM po_distributions_all
2241 WHERE po_header_id = l_supply_header_id
2242 AND line_location_id = l_supply_line_id
2243 GROUP BY po_header_id, po_line_id, line_location_id
2244 HAVING COUNT(DISTINCT NVL(project_id, -999)) = 1
2245 AND COUNT(DISTINCT NVL(task_id, -999)) = 1
2246 AND (l_project_ref_enabled = 2 OR
2247 l_allow_cross_proj_issues = 'Y' OR
2248 (NVL(MIN(project_id), -999) = NVL(p_project_id, -999) AND
2249 NVL(MIN(task_id), -999) = NVL(p_task_id, -999)))) pod
2250 WHERE rsl.po_header_id = l_supply_header_id
2251 AND rsl.po_line_location_id = l_supply_line_id
2252 AND rsl.shipment_line_id = l_supply_line_detail_id
2253 AND rsl.po_line_location_id = poll.line_location_id
2254 AND rsl.unit_of_measure = muom.unit_of_measure
2255 AND (p_uom_code IS NULL OR muom.uom_code = p_uom_code)
2256 AND pod.po_header_id = poll.po_header_id
2257 AND pod.po_line_id = poll.po_line_id
2258 AND pod.line_location_id = poll.line_location_id
2259 FOR UPDATE OF rsl.shipment_line_id, poll.line_location_id NOWAIT;
2260
2261 -- Cursor to lock the Internal Req supply line record.
2262 -- This can pull up multiple records if the given requisition line has several
2263 -- shipment lines tied to it. Each shipment line can be in a different UOM.
2264 -- For UOM integrity, if we want to match the UOM from the supply to the reservation,
2265 -- just use the UOM at the requisition line level.
2266 CURSOR lock_intreq_record(p_uom_code VARCHAR2, p_project_id NUMBER, p_task_id NUMBER) IS
2267 SELECT muom_prl.uom_code, prd.project_id, prd.task_id
2268 FROM po_requisition_lines_all prl, rcv_shipment_lines rsl, mtl_units_of_measure muom_prl,
2269 (SELECT requisition_line_id, MIN(project_id) AS project_id, MIN(task_id) AS task_id
2270 FROM po_req_distributions_all
2271 WHERE requisition_line_id = l_supply_line_id
2272 GROUP BY requisition_line_id
2273 HAVING COUNT(DISTINCT NVL(project_id, -999)) = 1
2274 AND COUNT(DISTINCT NVL(task_id, -999)) = 1
2275 AND (l_project_ref_enabled = 2 OR
2276 l_allow_cross_proj_issues = 'Y' OR
2277 (NVL(MIN(project_id), -999) = NVL(p_project_id, -999) AND
2278 NVL(MIN(task_id), -999) = NVL(p_task_id, -999)))) prd
2279 WHERE prl.requisition_header_id = l_supply_header_id
2280 AND prl.requisition_line_id = l_supply_line_id
2281 AND prl.unit_meas_lookup_code = muom_prl.unit_of_measure
2282 AND prl.requisition_line_id = rsl.requisition_line_id (+)
2283 AND (p_uom_code IS NULL OR muom_prl.uom_code = p_uom_code)
2284 AND prd.requisition_line_id = prl.requisition_line_id
2285 FOR UPDATE OF prl.requisition_line_id, rsl.shipment_line_id NOWAIT;
2286
2287 -- Cursor to lock the In Transit Shipment supply line record.
2288 CURSOR lock_intship_record(p_uom_code VARCHAR2, p_project_id NUMBER, p_task_id NUMBER) IS
2289 SELECT muom.uom_code, NULL AS project_id, NULL AS task_id
2290 FROM rcv_shipment_lines rsl, mtl_units_of_measure muom
2291 WHERE rsl.shipment_header_id = l_supply_header_id
2292 AND rsl.shipment_line_id = l_supply_line_id
2293 AND rsl.unit_of_measure = muom.unit_of_measure
2294 AND (p_uom_code IS NULL OR muom.uom_code = p_uom_code)
2295 AND (l_project_ref_enabled = 2 OR
2296 l_allow_cross_proj_issues = 'Y' OR
2297 (p_project_id IS NULL AND p_task_id IS NULL))
2298 FOR UPDATE OF rsl.shipment_line_id NOWAIT;
2299
2300 -- Cursor to lock and retrieve valid In Receiving supply move order lines.
2301 -- The MOLs will be ordered by ABS(mtrl.primary_quantity - p_rsv_prim_qty) ASC in order
2302 -- to minimize the amount of splitting that might need to be done for reservations and WDD
2303 -- demand lines. This ordering will find MOLs that are closest to the reservation quantity.
2304 -- MOLs which have the same primary quantity.
2305 -- We also want to match the project/task on the demand line to the MOL supply lines if
2306 -- cross project allocation is not allowed.
2307 CURSOR lock_receiving_lines(p_uom_code VARCHAR2,
2308 p_rsv_prim_qty NUMBER,
2309 p_project_id NUMBER,
2310 p_task_id NUMBER) IS
2311 SELECT
2312 mtrl.header_id AS header_id,
2313 mtrl.line_id AS line_id,
2314 NULL AS line_detail_id,
2315 mtrl.quantity AS quantity,
2316 mtrl.uom_code AS uom_code,
2317 mtrl.primary_quantity AS primary_quantity,
2318 mtrl.secondary_quantity AS secondary_quantity,
2319 mtrl.secondary_uom_code AS secondary_uom_code,
2320 mtrl.project_id AS project_id,
2321 mtrl.task_id AS task_id,
2322 mtrl.lpn_id AS lpn_id
2323 FROM mtl_txn_request_lines mtrl, mtl_txn_request_headers mtrh,
2324 wms_license_plate_numbers wlpn
2325 WHERE mtrl.header_id = mtrh.header_id
2326 AND mtrh.move_order_type = inv_globals.g_move_order_put_away
2327 AND mtrl.organization_id = l_organization_id
2328 AND mtrl.inventory_item_id = l_inventory_item_id
2329 -- Modified the line below to use an IN instead of <> so the
2330 -- index MTL_TXN_REQUEST_LINES_N10 on MTRL is more likely to be used.
2331 -- AND mtrl.line_status <> inv_globals.g_to_status_closed
2332 AND mtrl.line_status IN (inv_globals.g_to_status_preapproved,
2333 inv_globals.g_to_status_approved)
2334 AND mtrl.backorder_delivery_detail_id IS NULL
2335 AND mtrl.lpn_id IS NOT NULL
2336 AND mtrl.quantity > 0
2337 AND NVL(mtrl.quantity_delivered, 0) = 0
2338 AND NVL(mtrl.quantity_detailed, 0) = 0
2339 AND NVL(mtrl.inspection_status, 2) = 2
2340 AND NVL(mtrl.wms_process_flag, 1) = 1
2341 AND NVL(mtrl.reference, 'non-RMA') <> 'ORDER_LINE_ID'
2342 AND (p_uom_code IS NULL OR mtrl.uom_code = p_uom_code)
2343 AND (l_project_ref_enabled = 2 OR
2344 l_allow_cross_proj_issues = 'Y' OR
2345 (NVL(mtrl.project_id, -999) = NVL(p_project_id, -999) AND
2346 NVL(mtrl.task_id, -999) = NVL(p_task_id, -999)))
2347 AND mtrl.lpn_id = wlpn.lpn_id
2348 AND wlpn.lpn_context = 3
2349 -- Added the following line so the index: WMS_LICENSE_PLATE_NUMBERS_N6
2350 -- can be used in case the SQL optimizer uses WLPN as the driving table.
2351 AND wlpn.organization_id = l_organization_id
2352 ORDER BY ABS(mtrl.primary_quantity - p_rsv_prim_qty) ASC
2353 FOR UPDATE OF mtrl.line_id NOWAIT;
2354
2355 -- Table to store the results from the lock_receiving_lines cursor
2356 TYPE rcv_lines_tb IS TABLE OF lock_receiving_lines%ROWTYPE INDEX BY BINARY_INTEGER;
2357 l_rcv_lines_tb rcv_lines_tb;
2358
2359 -- Variables to store the converted quantity values and the available to detail
2360 -- values. They will all be converted to the UOM on the supply line, l_supply_uom_code.
2361 -- We also need the ATD qty in the primary UOM of the item.
2362 -- l_wdd_atr_txn_qty is used when the full quantity on the WDD line may not be available
2363 -- for crossdocking. This is not the case for existing reservations but is possible for
2364 -- normal crossdocking, i.e. other existing reservations tying up quantity on the WDD line.
2365 l_wdd_txn_qty NUMBER;
2366 l_wdd_atr_txn_qty NUMBER;
2367 l_rsv_txn_qty NUMBER;
2368 l_atd_qty NUMBER;
2369 l_atd_prim_qty NUMBER;
2370
2371 -- These values will store the available to detail quantity converted to the UOM of
2372 -- the WDD and RSV record respectively. They are used whenever those records need
2373 -- to be split. The secondary quantities are needed too when splitting a WDD or RSV record.
2374 -- For MOL records, the ATD quantity is always in that UOM. However, we still need to
2375 -- convert the ATD quantity to the secondary UOM on the MOL record if it exists.
2376 l_atd_wdd_qty NUMBER;
2377 l_atd_wdd_qty2 NUMBER;
2378 l_atd_rsv_qty NUMBER;
2379 l_atd_rsv_qty2 NUMBER;
2380 l_atd_mol_qty2 NUMBER;
2381
2382 -- Variables to store supply line info for supply source type of Receiving
2383 l_mol_qty NUMBER;
2384 l_mol_header_id NUMBER;
2385 l_mol_line_id NUMBER;
2386 l_mol_prim_qty NUMBER;
2387 l_mol_qty2 NUMBER;
2388 l_mol_uom_code2 VARCHAR2(3);
2389 l_mol_lpn_id NUMBER;
2390
2391 -- Conversion rate when converting quantity values to different UOMs
2392 l_conversion_rate NUMBER;
2393 -- The standard Inventory precision is to 5 decimal places. Define this in a local constant
2394 -- in case this needs to be changed later on. Variable is used to round off converted values
2395 -- to this precision level.
2396 l_conversion_precision CONSTANT NUMBER := 5;
2397
2398 -- Index used to loop through the supply lines for satisfying an existing reservation.
2399 -- For supplies of type non-Receiving, there is only one supply line used. However, for
2400 -- Receiving supply type, there are multiple MOL's that are possible to loop through.
2401 l_supply_index NUMBER;
2402
2403 -- Variables used to call the Shipping API to split a WDD line if a partial quantity
2404 -- is crossdocked on the WDD line.
2405 l_detail_id_tab WSH_UTIL_CORE.id_tab_type;
2406 l_action_prms WSH_GLBL_VAR_STRCT_GRP.dd_action_parameters_rec_type;
2407 l_action_out_rec WSH_GLBL_VAR_STRCT_GRP.dd_action_out_rec_type;
2408 l_split_wdd_rel_rec WSH_PR_CRITERIA.relRecTyp;
2409 l_split_wdd_id NUMBER;
2410 l_index NUMBER;
2411 l_next_index NUMBER;
2412
2413 -- Variables used to call the Shipping API to update a WDD line when it is
2414 -- being crossdocked.
2415 l_detail_info_tab WSH_INTERFACE_EXT_GRP.Delivery_Details_Attr_Tbl_Type;
2416 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
2417 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
2418
2419 -- Variables to split and update reservations records
2420 l_original_rsv_rec inv_reservation_global.mtl_reservation_rec_type;
2421 l_to_rsv_rec inv_reservation_global.mtl_reservation_rec_type;
2422 l_original_serial_number inv_reservation_global.serial_number_tbl_type;
2423 l_to_serial_number inv_reservation_global.serial_number_tbl_type;
2424 l_split_rsv_id NUMBER;
2425
2426 -- Variables to call the pregenerate API when MOL records are crossdocked
2427 -- to existing reservations.
2428 l_partial_success VARCHAR2(1);
2429 l_lpn_line_error_tbl wms_putaway_suggestions.lpn_line_error_tbl;
2430 l_lpn_index NUMBER;
2431
2432 -- Variables to store the available to reserve quantity for a demand or supply line
2433 -- both in the primary and demand/supply line UOM.
2434 l_demand_atr_prim_qty NUMBER;
2435 l_demand_atr_qty NUMBER;
2436 l_demand_available_qty NUMBER;
2437 l_supply_atr_prim_qty NUMBER;
2438 l_supply_atr_qty NUMBER;
2439 l_supply_available_qty NUMBER;
2440
2441 -- Cursor to retrieve eligible supply source types for a given crossdock criteria
2442 CURSOR supply_src_types_cursor IS
2443 SELECT source_code
2444 FROM wms_xdock_source_assignments
2445 WHERE criterion_id = l_crossdock_criteria_id
2446 AND source_type = G_SRC_TYPE_SUP
2447 ORDER BY priority;
2448
2449 -- Table to store the eligible supply source types indexed by crossdock criteria ID
2450 TYPE supply_src_types_tb IS TABLE OF num_tab INDEX BY BINARY_INTEGER;
2451 l_supply_src_types_tb supply_src_types_tb;
2452
2453 -- Table to store the valid supply lines for crossdocking for the current WDD demand.
2454 -- The type is defined in the specs instead so the custom logic package can reference it.
2455 l_shopping_basket_tb shopping_basket_tb;
2456
2457 -- Cursor to retrieve valid supply lines that fall within the crossdock window
2458 -- of the current demand.
2459 CURSOR get_supply_lines(p_xdock_start_time DATE,
2460 p_xdock_end_time DATE,
2461 p_sup_resched_flag NUMBER,
2462 p_sup_sched_method NUMBER,
2463 p_crossdock_goal NUMBER,
2464 p_past_due_interval INTERVAL DAY TO second,
2465 p_past_due_time NUMBER,
2466 p_po_sup NUMBER, p_po_priority NUMBER,
2467 p_asn_sup NUMBER, p_asn_priority NUMBER,
2468 p_intreq_sup NUMBER, p_intreq_priority NUMBER,
2469 p_intship_sup NUMBER, p_intship_priority NUMBER,
2470 p_rcv_sup NUMBER, p_rcv_priority NUMBER,
2471 p_demand_prim_qty NUMBER,
2472 p_project_id NUMBER,
2473 p_task_id NUMBER) IS
2474 SELECT ROWID,
2475 inventory_item_id,
2476 xdock_source_code,
2477 source_type_id,
2478 source_header_id,
2479 source_line_id,
2480 source_line_detail_id,
2481 dock_start_time,
2482 dock_mean_time,
2483 dock_end_time,
2484 expected_time,
2485 quantity,
2486 reservable_quantity,
2487 uom_code,
2488 primary_quantity,
2489 secondary_quantity,
2490 secondary_uom_code,
2491 project_id,
2492 task_id,
2493 lpn_id,
2494 wip_supply_type
2495 FROM wms_xdock_pegging_gtmp
2496 WHERE inventory_item_id = l_inventory_item_id
2497 AND xdock_source_code IN (p_po_sup, p_asn_sup, p_intreq_sup, p_intship_sup, p_rcv_sup)
2498 AND ((expected_time IS NOT NULL AND (p_past_due_time IS NULL OR
2499 expected_time > SYSDATE - p_past_due_interval)) OR
2500 (dock_start_time IS NOT NULL AND (p_past_due_time IS NULL OR
2501 dock_start_time > SYSDATE - p_past_due_interval)))
2502 -- Only pick up supply lines that match the project/task if necessary
2503 AND (l_project_ref_enabled = 2 OR
2504 l_allow_cross_proj_issues = 'Y' OR
2505 (NVL(project_id, -999) = NVL(p_project_id, -999) AND
2506 NVL(task_id, -999) = NVL(p_task_id, -999)))
2507 AND (-- Dock Appointment Exists
2508 (dock_start_time IS NOT NULL AND
2509 ((p_sup_sched_method = G_APPT_START_TIME AND
2510 dock_start_time BETWEEN p_xdock_start_time AND p_xdock_end_time) OR
2511 (p_sup_sched_method = G_APPT_MEAN_TIME AND
2512 dock_mean_time BETWEEN p_xdock_start_time AND p_xdock_end_time) OR
2513 (p_sup_sched_method = G_APPT_END_TIME AND
2514 dock_end_time BETWEEN p_xdock_start_time AND p_xdock_end_time))
2515 )
2516 -- No Dock Appointment but supply can be rescheduled
2517 OR (dock_start_time IS NULL AND p_sup_resched_flag = 1 AND
2518 expected_time BETWEEN TRUNC(p_xdock_start_time) AND
2519 TO_DATE(TO_CHAR(TRUNC(p_xdock_end_time), 'DD-MON-YYYY') ||
2520 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS')
2521 )
2522 -- No Dock Appointment and supply cannot be rescheduled
2523 OR (dock_start_time IS NULL AND p_sup_resched_flag = 2 AND
2524 expected_time BETWEEN p_xdock_start_time AND p_xdock_end_time
2525 )
2526 )
2527 ORDER BY DECODE (xdock_source_code,
2528 G_PLAN_SUP_PO_APPR, p_po_priority,
2529 G_PLAN_SUP_ASN, p_asn_priority,
2530 G_PLAN_SUP_REQ, p_intreq_priority,
2531 G_PLAN_SUP_INTR, p_intship_priority,
2532 G_PLAN_SUP_RCV, p_rcv_priority,
2533 99),
2534 -- For In Receiving supply lines, order by the quantity closest to the
2535 -- ATR demand qty we are crossdocking for. The expected times should all
2536 -- be the same since the material has already been received.
2537 -- Putting this order by first before the crossdocking goal since only
2538 -- In Receiving supply lines will have a non-null value for primary_quantity.
2539 -- For other supply types, this order by will do nothing. Doing this since the
2540 -- expected time for In Receiving lines just use SYSDATE. We do not want the
2541 -- order the MOL's are encountered and inserted into wms_xdock_pegging_gtmp to
2542 -- affect the order we consume them for crossdocking.
2543 ABS(NVL(primary_quantity, 0) - p_demand_prim_qty) ASC,
2544 DECODE (p_crossdock_goal,
2545 G_MINIMIZE_WAIT, SYSDATE - NVL(expected_time, dock_start_time),
2546 G_MAXIMIZE_XDOCK, NVL(expected_time, dock_start_time) - SYSDATE,
2547 G_CUSTOM_GOAL, NULL,
2548 NULL);
2549
2550 -- Variables for the get_supply_lines cursor to indicate which supply source
2551 -- types/codes to retrieve valid supply lines for. If the supply type is not used,
2552 -- a value of -1 will be defaulted. If it is used, the corresponding supply source code
2553 -- that crossdock criteria uses will be passed.
2554 l_po_sup NUMBER;
2555 l_asn_sup NUMBER;
2556 l_intreq_sup NUMBER;
2557 l_intship_sup NUMBER;
2558 l_rcv_sup NUMBER;
2559
2560 -- Variables for the get_supply_lines cursor to indicate the relative priority of the supply
2561 -- source types to retrieve valid supply lines for. If we don't need to prioritize documents,
2562 -- a default value of 99 will be used. The cursor get_supply_lines will order by the priority
2563 -- value in ascending order so lower values have higher priority.
2564 l_po_priority NUMBER;
2565 l_asn_priority NUMBER;
2566 l_intreq_priority NUMBER;
2567 l_intship_priority NUMBER;
2568 l_rcv_priority NUMBER;
2569
2570 -- Variables to deal with rolling back the changes to the PLSQL data structures:
2571 -- p_wsh_release_table, p_trolin_delivery_ids and p_del_detail_id in case a rollback
2572 -- occurs. The rollback will deal with the database changes to WDD, RSV, and MOL records.
2573 -- However, we are locally storing the changes to WDD records in the data structures
2574 -- mentioned above. We should clean that up and rollback the similar changes made there.
2575 -- Also need to keep track of the WDD values inserted into WSH_PICK_LIST.G_XDOCK_DETAIL_TAB
2576 -- and WSH_PICK_LIST.G_XDOCK_MOL_TAB used for updating the crossdocked WDD records.
2577 l_split_wdd_index NUMBER;
2578 l_split_delivery_index NUMBER;
2579 l_xdocked_wdd_index NUMBER;
2580
2581 -- Type used to store the original WDD values that were modified when crossdocked
2582 TYPE orig_wdd_values_rec IS RECORD
2583 (requested_quantity NUMBER,
2584 requested_quantity2 NUMBER,
2585 released_status VARCHAR2(1),
2586 move_order_line_id NUMBER);
2587 l_orig_wdd_values_rec orig_wdd_values_rec;
2588
2589 -- The following are types used to keep track of which set of MOLs have already been
2590 -- locked as valid supply lines for crossdocking. The three keys to this are the
2591 -- inventory item, project ID, and task ID. This will keep track of what project and task
2592 -- MOLs have already been locked for crossdocking using a nested PLSQL table structure.
2593 -- The project and task part are only stored if the org is PJM enabled AND cross project
2594 -- allocation is not allowed. In that case, the set of MOLs locked will be for a specific
2595 -- project and task matched to ones on the current demand line. Null values of project
2596 -- and task will use -999 as the ID. If the org is not PJM enabled OR cross project allocation
2597 -- is allowed, we just need to insert a dummy project/task part for the given item.
2598 -- e.g. l_locked_mols_tb(l_inventory_item_id)(-999)(-999) := TRUE; In that case, we just need
2599 -- to check that a value exists for the item, i.e. l_locked_mols_tb.EXISTS(l_inventory_item_id).
2600 -- There is no need to go to the project/task levels.
2601 TYPE task_id_tb IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER;
2602 TYPE project_id_tb IS TABLE OF task_id_tb INDEX BY BINARY_INTEGER;
2603 TYPE locked_mols_tb IS TABLE OF project_id_tb INDEX BY BINARY_INTEGER;
2604 l_locked_mols_tb locked_mols_tb;
2605 l_dummy_project_id NUMBER := -999;
2606 l_dummy_task_id NUMBER := -999;
2607
2608 -- The following are variables used to call the create_reservation API
2609 l_quantity_reserved NUMBER;
2610 l_quantity_reserved2 NUMBER;
2611
2612 -- The following is a table indexed by LPN ID to indicate which LPNs contained MOLs that
2613 -- were crossdocked. This set of MOLs need to call the pre-generate API so the crossdock
2614 -- tasks can be generated.
2615 TYPE crossdocked_lpns_tb IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER;
2616 l_crossdocked_lpns_tb crossdocked_lpns_tb;
2617
2618 -- Table storing the delivery detail ID's for backordered lines. These records
2619 -- should be removed from the input tables, p_trolin_delivery_ids and p_del_detail_id
2620 -- for allocation mode of N (Prioritize Inventory).
2621 -- This is so deliveries are not autocreated for them later on by Shipping.
2622 l_backordered_wdd_tbl bool_tab;
2623 l_backordered_wdd_lines PLS_INTEGER;
2624
2625 -- Variable used to call the Shipping API to backorder WDD lines.
2626 -- This is used for allocation mode of N (Prioritize Inventory).
2627 l_shipping_attr WSH_INTERFACE.ChangedAttributeTabType;
2628
2629 -- Variables used to bulk update the reservable_quantity column in the global temp table,
2630 -- wms_xdock_pegging_gtmp. We want to do a bulk update for this in case multiple
2631 -- supply lines are consumed when crossdocking a WDD record.
2632 l_supply_atr_index NUMBER;
2633 TYPE rowid_tab IS TABLE OF urowid INDEX BY BINARY_INTEGER;
2634 l_supply_rowid_tb rowid_tab;
2635 l_supply_atr_qty_tb num_tab;
2636
2637 -- Variables used when calling custom logic to sort the supply lines in the
2638 -- shopping basket table.
2639 l_sorted_order_tb sorted_order_tb;
2640 l_shopping_basket_temp_tb shopping_basket_tb;
2641 l_indices_used_tb bool_tab;
2642
2643 -- Error code variable used when calling the private Crossdock_WDD and Crossdock_MOL
2644 -- procedures. This will indicate if an exception occurred during UOM conversion or
2645 -- during a database operation.
2646 -- Possible values are: UOM - UOM Conversion error
2647 -- DB - Database Update error
2648 l_error_code VARCHAR2(3);
2649
2650 -- Dummy variables used for calling Crossdock_MOL. These values are used for
2651 -- WIP demand lines for Opportunistic Crossdock.
2652 l_wip_entity_id NUMBER;
2653 l_repetitive_schedule_id NUMBER;
2654 l_operation_seq_num NUMBER;
2655 l_wip_supply_type NUMBER;
2656
2657 -- Variable for Allocation method of 'Crossdock Only' to indicate if any of the
2658 -- input demand release lines were unable to be crossdocked. This is used so
2659 -- Shipping can display a status of 'Warning' to the user to indicate that some
2660 -- of the lines were unable to be allocated for whatever reason.
2661 l_unable_to_crossdock BOOLEAN := FALSE;
2662
2663 l_wave_header_id number;
2664
2665 l_new_mol_id number;
2666
2667
2668 BEGIN
2669 -- Start the profiler for Unit Testing to ensure complete code coverage
2670 --dbms_profiler.start_profiler('Planned_Cross_Dock: ' || p_batch_id);
2671
2672 IF (l_debug = 1) THEN
2673 print_debug('***Calling Planned_Cross_Dock with the following parameters***');
2674 print_debug('Package Version: => ' || g_pkg_version);
2675 print_debug('p_api_version: ===> ' || p_api_version);
2676 print_debug('p_init_msg_list: => ' || p_init_msg_list);
2677 print_debug('p_commit: ========> ' || p_commit);
2678 print_debug('p_batch_id: ======> ' || p_batch_id);
2679 END IF;
2680
2681 -- Set the savepoint
2682 SAVEPOINT Planned_Cross_Dock_sp;
2683 l_progress := '10';
2684
2685 l_simulation_mode := p_simulation_mode;
2686
2687 -- Standard Call to check for call compatibility
2688 IF NOT fnd_api.Compatible_API_Call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
2689 IF (l_debug = 1) THEN
2690 print_debug('FND_API version not compatible!');
2691 END IF;
2692 RAISE fnd_api.g_exc_unexpected_error;
2693 END IF;
2694
2695 -- Initialize message list to clear any existing messages
2696 IF fnd_api.To_Boolean(p_init_msg_list) THEN
2697 fnd_msg_pub.initialize;
2698 END IF;
2699 l_progress := '20';
2700
2701 -- Initialize API return status to success
2702 x_return_status := fnd_api.g_ret_sts_success;
2703 l_progress := '30';
2704
2705 -- Return if there are no records to crossdock in p_wsh_release_table.
2706 -- {{
2707 -- If no records exist in the release table, API should still process without error. }}
2708 IF (p_wsh_release_table.COUNT = 0) THEN
2709 IF (l_debug = 1) THEN
2710 print_debug('No records in p_wsh_release_table, exiting.');
2711 END IF;
2712 RETURN;
2713 END IF;
2714
2715 -- Initialize the PLSQL tables used to retrieve the supply line cursor records
2716 l_header_id_tb.DELETE;
2717 l_line_id_tb.DELETE;
2718 l_line_detail_id_tb.DELETE;
2719 l_dock_start_time_tb.DELETE;
2720 l_dock_mean_time_tb.DELETE;
2721 l_dock_end_time_tb.DELETE;
2722 l_expected_time_tb.DELETE;
2723 l_quantity_tb.DELETE;
2724 l_uom_code_tb.DELETE;
2725 l_primary_quantity_tb.DELETE;
2726 l_secondary_quantity_tb.DELETE;
2727 l_secondary_uom_code_tb.DELETE;
2728 l_project_id_tb.DELETE;
2729 l_task_id_tb.DELETE;
2730 l_lpn_id_tb.DELETE;
2731
2732 -- Initialize the source types retrieved table
2733 l_src_types_retrieved_tb.DELETE;
2734
2735 -- Initialize the item parameters table
2736 l_item_params_tb.DELETE;
2737
2738 -- Initialize the UOM class table
2739 l_uom_class_tb.DELETE;
2740
2741 -- Initialize the global Item UOM conversion table
2742 g_item_uom_conversion_tb.DELETE;
2743
2744 -- Initialize the eligible supply source types table
2745 l_supply_src_types_tb.DELETE;
2746
2747 -- Initialize the locked MOL's table
2748 l_locked_mols_tb.DELETE;
2749
2750 -- Initialize the crossdocked LPN's table
2751 l_crossdocked_lpns_tb.DELETE;
2752
2753 -- Initialize the detail info table used for updating
2754 -- crossdocked WDD records
2755 l_detail_info_tab.DELETE;
2756
2757 -- Initialize the crossdock criteria cache table
2758 g_crossdock_criteria_tb.DELETE;
2759 l_progress := '40';
2760
2761 -- Query for and cache the picking batch record for the inputted batch ID
2762 -- {{
2763 -- Test for invalid batch ID entered. API should error out. }}
2764
2765 if p_simulation_mode = 'N' THEN
2766
2767 IF (NOT INV_CACHE.set_wpb_rec
2768 (p_batch_id => p_batch_id,
2769 p_request_number => NULL)) THEN
2770 IF (l_debug = 1) THEN
2771 print_debug('Error caching the WSH picking batch record');
2772 END IF;
2773 RAISE fnd_api.g_exc_unexpected_error;
2774 END IF;
2775 end if;
2776 l_progress := '50';
2777
2778
2779 if p_simulation_mode = 'Y' THEN
2780
2781
2782 print_debug('Getting the Crossdock Parameters based on Planning Criteria ID --- > SImulation Mode');
2783
2784
2785
2786 select wwh.organization_id,allocation_method,crossdock_criteria_id,wave_header_id
2787 into l_organization_id,l_allocation_method,l_wpb_xdock_criteria_id,l_wave_header_id
2788 from wms_wp_planning_criteria_vl wwp,wms_wp_wave_headers_vl wwh
2789 where wwp.planning_criteria_id = WMS_WAVE_PLANNING_PVT.g_planning_criteria_id
2790 AND wwh.planning_criteria_id=wwp.planning_criteria_id;
2791
2792
2793 else --- p_simulation_mode = 'N' --Existing Code
2794 -- Retrieve the necessary parameters from the picking batch
2795 -- {{
2796 -- Test for multiple orgs tied to the picking batch. }}
2797 -- If multiple orgs are tied to the picking batch, there should still be only one
2798 -- org for the sub-batch passed to the crossdock API. Just retrieve the org from
2799 -- p_wsh_release_table instead.
2800 --l_organization_id := inv_cache.wpb_rec.organization_id;
2801 l_organization_id := p_wsh_release_table(p_wsh_release_table.FIRST).organization_id;
2802 l_allocation_method := NVL(inv_cache.wpb_rec.allocation_method, G_INVENTORY_ONLY);
2803 l_wpb_xdock_criteria_id := inv_cache.wpb_rec.crossdock_criteria_id;
2804 l_existing_rsvs_only := NVL(inv_cache.wpb_rec.existing_rsvs_only_flag, 'N');
2805 l_progress := '60';
2806
2807 -- Query for and cache the org record.
2808 IF (NOT INV_CACHE.set_org_rec(l_organization_id)) THEN
2809 IF (l_debug = 1) THEN
2810 print_debug('Error caching the org record');
2811 END IF;
2812 RAISE fnd_api.g_exc_unexpected_error;
2813 END IF;
2814
2815 end if; -- For SImulation Mode
2816 -- Set the PJM enabled flag.
2817 l_project_ref_enabled := INV_CACHE.org_rec.project_reference_enabled;
2818 l_progress := '70';
2819
2820 -- Check if the organization is a WMS organization
2821 l_wms_org_flag := wms_install.check_install
2822 (x_return_status => x_return_status,
2823 x_msg_count => x_msg_count,
2824 x_msg_data => x_msg_data,
2825 p_organization_id => l_organization_id);
2826 IF (x_return_status <> fnd_api.g_ret_sts_success) THEN
2827 IF (l_debug = 1) THEN
2828 print_debug('Call to wms_install.check_install failed: ' || x_msg_data);
2829 END IF;
2830 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2831 END IF;
2832 l_progress := '80';
2833
2834 -- Retrieve the org parameter for allowing cross project allocation for crossdocking.
2835 -- For now, just hardcode this to 'N'. The reason is even if we create a peg with
2836 -- differing project/task combinations, execution needs to be able to handle this.
2837 -- A project/task transfer needs to be done so until that code is present, we should not
2838 -- create cross project pegs. The following is the SQL for retrieving this value.
2839 /*IF (l_project_ref_enabled = 1) THEN
2840 -- PJM org so see if cross project allocation is allowed
2841 BEGIN
2842 SELECT NVL(allow_cross_proj_issues, 'N')
2843 INTO l_allow_cross_proj_issues
2844 FROM pjm_org_parameters
2845 WHERE organization_id = l_organization_id;
2846 EXCEPTION
2847 WHEN OTHERS THEN
2848 l_allow_cross_proj_issues := 'N';
2849 END;
2850 ELSE
2851 -- Non-PJM org so cross project allocation is allowed since there are no projects or tasks
2852 l_allow_cross_proj_issues := 'Y';
2853 END IF;*/
2854 l_allow_cross_proj_issues := 'N';
2855 l_progress := '90';
2856
2857 -- Validate that the allocation method is not Inventory Only
2858 -- {{
2859 -- Make sure API errors out if the allocation method is Inventory Only. }}
2860 IF (l_allocation_method = G_INVENTORY_ONLY) THEN
2861 IF (l_debug = 1) THEN
2862 print_debug('Allocation method of Inventory Only is invalid');
2863 END IF;
2864 RAISE fnd_api.g_exc_unexpected_error;
2865 END IF;
2866 l_progress := '100';
2867
2868 -- Query for and cache the crossdock criteria record for the picking batch
2869 -- if a value exists. This crossdock criterion will be used for all of the
2870 -- WDD records to be crossdocked.
2871 -- {{
2872 -- API should error out if invalid crossdock criteria is passed from the picking batch. }}
2873 IF (l_wpb_xdock_criteria_id IS NOT NULL) THEN
2874 IF (NOT set_crossdock_criteria(l_wpb_xdock_criteria_id)) THEN
2875 IF (l_debug = 1) THEN
2876 print_debug('Error caching the crossdock criteria record: ' ||
2877 l_wpb_xdock_criteria_id);
2878 END IF;
2879 RAISE fnd_api.g_exc_unexpected_error;
2880 END IF;
2881 END IF;
2882 l_progress := '110';
2883 -- End of validations and initializations
2884
2885
2886 -- Loop through the release table and try to crossdock records with
2887 -- a released status of 'R' or 'B'.
2888 l_wdd_index := p_wsh_release_table.FIRST;
2889 LOOP
2890 -- Crossdock the current WDD record only if it has a released status of R or B.
2891 -- Do not crossdock any of the WDD records if the org is not a WMS org. We still need
2892 -- to do some post-crossdocking logic for certain cases if this API is called for a
2893 -- non WMS org, e.g. backordering the unallocated WDD lines for Prioritize Inventory.
2894 -- {{
2895 -- WDD records with a released status other than R or B should not be crossdocked. }}
2896 -- {{
2897 -- Test for crossdock API called for a non WMS org. Post crossdock logic should still
2898 -- be done, such as backordering the unallocated WDD lines for Prioritize Inventory. }}
2899 IF (p_wsh_release_table(l_wdd_index).released_status NOT IN ('R','B') OR
2900 NOT l_wms_org_flag) THEN
2901 GOTO next_record;
2902 END IF;
2903
2904 -- Section 1: Demand line validations and initializations
2905 -- For the current demand line, perform the following validations and
2906 -- initializations on it.
2907 -- 1.1 - Validate that the demand line is eligible for crossdocking.
2908 -- 1.2 - Lock the demand line record.
2909 -- 1.3 - Retrieve and store the crossdock criterion for the demand line.
2910 -- 1.4 - Determine the expected ship date for the demand line.
2911 -- Calculate the crossdock window given the expected ship date and crossdock
2912 -- criteria time parameters.
2913
2914 -- Retrieve necessary parameters for the current demand line from p_wsh_release_table
2915 --l_organization_id := p_wsh_release_table(l_wdd_index).organization_id;
2916 l_inventory_item_id := p_wsh_release_table(l_wdd_index).inventory_item_id;
2917 l_demand_header_id := p_wsh_release_table(l_wdd_index).source_header_id;
2918 l_demand_so_header_id := inv_salesorder.get_salesorder_for_oeheader(l_demand_header_id);
2919 l_demand_line_id := p_wsh_release_table(l_wdd_index).source_line_id;
2920 l_demand_line_detail_id := p_wsh_release_table(l_wdd_index).delivery_detail_id;
2921 l_demand_qty := p_wsh_release_table(l_wdd_index).requested_quantity;
2922 l_demand_uom_code := p_wsh_release_table(l_wdd_index).requested_quantity_uom;
2923 l_demand_qty2 := p_wsh_release_table(l_wdd_index).requested_quantity2;
2924 l_demand_uom_code2 := p_wsh_release_table(l_wdd_index).requested_quantity_uom2;
2925 l_demand_project_id := p_wsh_release_table(l_wdd_index).project_id;
2926 l_demand_task_id := p_wsh_release_table(l_wdd_index).task_id;
2927 IF (NVL(p_wsh_release_table(l_wdd_index).source_doc_type, -999) <> 10) THEN
2928 -- Sales Order
2929 l_demand_type_id := 2;
2930 ELSE
2931 -- Internal Order
2932 l_demand_type_id := 8;
2933 END IF;
2934 IF (l_debug = 1) THEN
2935 print_debug('1.0 - Current WDD to crossdock: ==> ' || l_demand_line_detail_id);
2936 print_debug('1.0 - Current Item to crossdock: => ' || l_inventory_item_id);
2937 END IF;
2938
2939 -- 1.1 - Validate that the demand line is eligible for crossdocking.
2940 IF (l_debug = 1) THEN
2941 print_debug('1.1 - Validate that the demand line is eligible for crossdocking');
2942 END IF;
2943
2944 -- Make sure current WDD is not associated with a ship set or ship model.
2945 -- {{
2946 -- WDD demand lines tied to ship sets or ship models should not be crossdocked. }}
2947 IF (l_debug = 1) THEN
2948 print_debug('1.1 - Ship Set ID: ========> ' ||
2949 p_wsh_release_table(l_wdd_index).ship_set_id);
2950 print_debug('1.1 - Top Model Line ID: ==> ' ||
2951 p_wsh_release_table(l_wdd_index).top_model_line_id);
2952 END IF;
2953 IF (p_wsh_release_table(l_wdd_index).ship_set_id IS NOT NULL OR
2954 p_wsh_release_table(l_wdd_index).top_model_line_id IS NOT NULL) THEN
2955 IF (l_debug = 1) THEN
2956 print_debug('1.1 - Do not crossdock ship set or ship model WDD lines');
2957 END IF;
2958 GOTO next_record;
2959 END IF;
2960
2961 -- Query for and cache the item parameters needed.
2962 -- {{
2963 -- If item parameter information cannot be retrieved, make sure we just go on to the
2964 -- next WDD record to crossdock. }}
2965 IF (NOT l_item_params_tb.EXISTS(l_inventory_item_id)) THEN
2966 BEGIN
2967 SELECT primary_uom_code, NVL(reservable_type, 1),
2968 NVL(lot_control_code, 1), NVL(lot_divisible_flag, 'Y'), item_type
2969 INTO l_item_params_tb(l_inventory_item_id)
2970 FROM mtl_system_items
2971 WHERE inventory_item_id = l_inventory_item_id
2972 AND organization_id = l_organization_id;
2973 EXCEPTION
2974 WHEN OTHERS THEN
2975 IF (l_debug = 1) THEN
2976 print_debug('1.1 - Error caching the item parameters: ' ||
2977 l_inventory_item_id);
2978 END IF;
2979 GOTO next_record;
2980 --RAISE fnd_api.g_exc_unexpected_error;
2981 END;
2982 END IF;
2983 -- Store the item's primary UOM code in a local variable
2984 l_primary_uom_code := l_item_params_tb(l_inventory_item_id).primary_uom_code;
2985
2986 --16509516 and 16466246
2987 --For Order Lines Fulfilled by Secondary UoM, do not consider them to XDock
2988 IF(NVL(OE_DUAL_UOM_UTIL.get_fulfillment_base(p_wsh_release_table(l_wdd_index).source_line_id),'P') = 'S') THEN
2989 IF (l_debug = 1) THEN
2990 print_debug('Do not crossdock FB=S Lines, Order Line: '||p_wsh_release_table(l_wdd_index).source_line_id);
2991 print_debug('Skip this Delivery Detail, WDD: '||p_wsh_release_table(l_wdd_index).delivery_detail_id);
2992 END IF;
2993 GOTO next_record;
2994 END IF;
2995 --16509516
2996
2997 -- Make sure the item is reservable.
2998 -- {{
2999 -- Non-reservable items should not be crossdocked. }}
3000 IF (l_debug = 1) THEN
3001 print_debug('1.1 - Reservable Type: ====> ' ||
3002 l_item_params_tb(l_inventory_item_id).reservable_type);
3003 END IF;
3004 IF (l_item_params_tb(l_inventory_item_id).reservable_type = 2) THEN
3005 IF (l_debug = 1) THEN
3006 print_debug('1.1 - Do not crossdock non-reservable items');
3007 END IF;
3008 GOTO next_record;
3009 END IF;
3010
3011 -- Make sure the item is lot divisible if it is lot controlled.
3012 -- {{
3013 -- Lot Indivisible items should not be crossdocked. }}
3014 IF (l_debug = 1) THEN
3015 print_debug('1.1 - Lot Control Code: ===> ' ||
3016 l_item_params_tb(l_inventory_item_id).lot_control_code);
3017 print_debug('1.1 - Lot Divisible Flag: => ' ||
3018 l_item_params_tb(l_inventory_item_id).lot_divisible_flag);
3019 END IF;
3020 IF (l_item_params_tb(l_inventory_item_id).lot_control_code = 2 AND
3021 l_item_params_tb(l_inventory_item_id).lot_divisible_flag = 'N') THEN
3022 IF (l_debug = 1) THEN
3023 print_debug('1.1 - Do not crossdock lot indivisible items');
3024 END IF;
3025 GOTO next_record;
3026 END IF;
3027 l_progress := '120';
3028
3029 -- If we do not allow partial WIP crossdocking, that is a mix of demand being tied to
3030 -- both WIP and other non-Inventory supply sources, validate that the current demand
3031 -- it not already tied to WIP supply.
3032 IF (WMS_XDOCK_CUSTOM_APIS_PUB.g_allow_partial_wip_xdock = 'N') THEN
3033 IF (WMS_XDOCK_PEGGING_PUB.is_demand_tied_to_wip
3034 (p_organization_id => l_organization_id,
3035 p_inventory_item_id => l_inventory_item_id,
3036 p_demand_type_id => l_demand_type_id,
3037 p_demand_header_id => l_demand_so_header_id,
3038 p_demand_line_id => l_demand_line_id) = 'Y') THEN
3039 IF (l_debug = 1) THEN
3040 print_debug('1.1 - Do not crossdock demand already tied to WIP supply');
3041 END IF;
3042 GOTO next_record;
3043 END IF;
3044 END IF;
3045 l_progress := '125';
3046
3047 -- 1.2 - Lock the demand line record.
3048 -- {{
3049 -- If the WDD demand line cannot be locked, move on to the next record. }}
3050 IF (l_debug = 1) THEN
3051 print_debug('1.2 - Lock the demand line record: ' || l_demand_line_detail_id);
3052 END IF;
3053 BEGIN
3054 OPEN lock_wdd_record(l_demand_line_detail_id);
3055 CLOSE lock_wdd_record;
3056 EXCEPTION
3057 WHEN OTHERS THEN
3058 IF (l_debug = 1) THEN
3059 print_debug('1.2 - Could not lock the current WDD record: ' ||
3060 l_demand_line_detail_id);
3061 END IF;
3062 -- If unable to lock the current WDD record for some reason, do not error out.
3063 -- Just skip it and try to crossdock the next WDD record.
3064 GOTO next_record;
3065 END;
3066 l_progress := '130';
3067
3068 -- 1.3 - Retrieve and store the crossdock criterion for the demand line.
3069 IF (l_debug = 1) THEN
3070 print_debug('1.3 - Retrieve and store the crossdock criterion for the demand line');
3071 END IF;
3072 IF (l_wpb_xdock_criteria_id IS NOT NULL) THEN
3073 -- Use the crossdock criteria inputted for the picking batch.
3074 -- This record should already be queried for and cached.
3075 l_crossdock_criteria_id := l_wpb_xdock_criteria_id;
3076 ELSE
3077 -- Query for and cache the UOM class for the current UOM code.
3078 -- {{
3079 -- If the UOM class cannot be retrieved, just move on to the next WDD record. }}
3080 IF (NOT l_uom_class_tb.EXISTS(l_demand_uom_code)) THEN
3081 BEGIN
3082 SELECT uom_class
3083 INTO l_uom_class_tb(l_demand_uom_code)
3084 FROM mtl_units_of_measure
3085 WHERE uom_code = l_demand_uom_code;
3086 EXCEPTION
3087 WHEN OTHERS THEN
3088 IF (l_debug = 1) THEN
3089 print_debug('1.3 - Error caching the UOM class: ' || l_demand_uom_code);
3090 END IF;
3091 --GOTO next_record;
3092 --RAISE fnd_api.g_exc_unexpected_error;
3093 -- Instead of skipping to the next record, just store a NULL value
3094 -- for the UOM class. The crossdock criteria retrieved will thus not
3095 -- make use of the UOM class as a filter.
3096 l_uom_class_tb(l_demand_uom_code) := NULL;
3097 END;
3098 END IF;
3099
3100 -- Call the custom API to determine a valid crossdock criteria first.
3101 -- If this API is not implemented, it will just be a stub and return a value of
3102 -- FALSE for x_api_is_implemented.
3103 -- {{
3104 -- Test for an implemented custom API to get the crossdock criteria. We should not
3105 -- call the rules engine in this case. }}
3106 WMS_XDOCK_CUSTOM_APIS_PUB.Get_Crossdock_Criteria
3107 (p_wdd_release_record => p_wsh_release_table(l_wdd_index),
3108 x_return_status => x_return_status,
3109 x_msg_count => x_msg_count,
3110 x_msg_data => x_msg_data,
3111 x_api_is_implemented => l_api_is_implemented,
3112 x_crossdock_criteria_id => l_crossdock_criteria_id);
3113
3114 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
3115 IF (l_debug = 1) THEN
3116 print_debug('1.3 - Success returned from Get_Crossdock_Criteria API');
3117 END IF;
3118 ELSE
3119 IF (l_debug = 1) THEN
3120 print_debug('1.3 - Failure returned from Get_Crossdock_Criteria API');
3121 END IF;
3122 GOTO next_record;
3123 --RAISE fnd_api.g_exc_error;
3124 END IF;
3125
3126 -- If the custom API is not implemented, call the rules engine to determine the
3127 -- crossdock criteria for the current WDD record.
3128 IF (NOT l_api_is_implemented) THEN
3129 -- Call the rules engine to retrieve the crossdock criteria
3130 -- for the current WDD record
3131 -- {{
3132 -- If the rules errors out while determining a crossdock criteria, just go to the
3133 -- next WDD record. }}
3134 IF (l_debug = 1) THEN
3135 print_debug('1.3 - Call the cross_dock_search Rules Workbench API');
3136 END IF;
3137 wms_rules_workbench_pvt.cross_dock_search
3138 ( p_rule_type_code => G_CRT_RULE_TYPE_PLAN,
3139 p_organization_id => l_organization_id,
3140 p_customer_id => p_wsh_release_table(l_wdd_index).customer_id,
3141 p_inventory_item_id => l_inventory_item_id,
3142 p_item_type => l_item_params_tb(l_inventory_item_id).item_type,
3143 p_vendor_id => NULL,
3144 p_location_id => p_wsh_release_table(l_wdd_index).ship_from_location_id,
3145 p_project_id => p_wsh_release_table(l_wdd_index).project_id,
3146 p_task_id => p_wsh_release_table(l_wdd_index).task_id,
3147 p_user_id => FND_GLOBAL.user_id,
3148 p_uom_code => l_demand_uom_code,
3149 p_uom_class => l_uom_class_tb(l_demand_uom_code),
3150 x_return_type => l_return_type,
3151 x_return_type_id => l_crossdock_criteria_id,
3152 x_sequence_number => l_sequence_number,
3153 x_return_status => x_return_status);
3154
3155 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
3156 IF (l_debug = 1) THEN
3157 print_debug('1.3 - Success returned from cross_dock_search API');
3158 END IF;
3159 ELSE
3160 IF (l_debug = 1) THEN
3161 print_debug('1.3 - Failure returned from cross_dock_search API');
3162 END IF;
3163 GOTO next_record;
3164 --RAISE fnd_api.g_exc_error;
3165 END IF;
3166 END IF;
3167
3168 -- Query for and cache the crossdock criteria retrieved from the rules engine
3169 IF (l_crossdock_criteria_id IS NOT NULL) THEN
3170 IF (NOT set_crossdock_criteria(l_crossdock_criteria_id)) THEN
3171 IF (l_debug = 1) THEN
3172 print_debug('1.3 - Error caching the crossdock criteria record: ' ||
3173 l_crossdock_criteria_id);
3174 END IF;
3175 GOTO next_record;
3176 --RAISE fnd_api.g_exc_unexpected_error;
3177 END IF;
3178 END IF;
3179
3180 END IF; -- END IF matching 'IF (l_wpb_xdock_criteria_id IS NOT NULL) THEN'
3181 IF (l_debug = 1) THEN
3182 print_debug('1.3 - Crossdock Criteria ID to use: ' || l_crossdock_criteria_id);
3183 END IF;
3184 -- Do not crossdock WDD record if a crossdock criteria is not retrieved.
3185 -- {{
3186 -- If a crossdock criteria is not returned by the rules engine, stop processing
3187 -- and move on to the next WDD record to crossdock. }}
3188 IF (l_crossdock_criteria_id IS NULL) THEN
3189 GOTO next_record;
3190 END IF;
3191 l_progress := '140';
3192
3193 -- 1.4 - Determine the expected ship date for the demand line.
3194 -- Calculate the crossdock window given the expected ship date and crossdock
3195 -- criteria time parameters.
3196 IF (l_debug = 1) THEN
3197 print_debug('1.4 - Determine the expected ship date for the demand line');
3198 END IF;
3199 Get_Expected_Time
3200 (p_source_type_id => l_demand_type_id,
3201 p_source_header_id => l_demand_so_header_id,
3202 p_source_line_id => l_demand_line_id,
3203 p_source_line_detail_id => l_demand_line_detail_id,
3204 p_supply_or_demand => G_SRC_TYPE_DEM,
3205 p_crossdock_criterion_id => l_crossdock_criteria_id,
3206 x_return_status => x_return_status,
3207 x_msg_count => x_msg_count,
3208 x_msg_data => x_msg_data,
3209 x_dock_start_time => l_dock_start_time,
3210 x_dock_mean_time => l_dock_mean_time,
3211 x_dock_end_time => l_dock_end_time,
3212 x_expected_time => l_demand_expected_time);
3213
3214 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
3215 IF (l_debug = 1) THEN
3216 print_debug('1.4 - Success returned from Get_Expected_Time API');
3217 END IF;
3218 ELSE
3219 IF (l_debug = 1) THEN
3220 print_debug('1.4 - Failure returned from Get_Expected_Time API');
3221 END IF;
3222 GOTO next_record;
3223 --RAISE fnd_api.g_exc_error;
3224 END IF;
3225 -- Use this value to determine if a dock appointment for the demand line exists.
3226 -- There is a parameter on the crossdock criteria to decide if we should schedule
3227 -- demand anytime on the shipment date if no dock appointment exists.
3228 IF (l_dock_start_time IS NOT NULL) THEN
3229 l_demand_dock_exists := TRUE;
3230 ELSE
3231 l_demand_dock_exists := FALSE;
3232 END IF;
3233 -- Do not crossdock WDD record if an expected time cannot be determined.
3234 -- {{
3235 -- If the expected time for the WDD demand cannot be determined, stop processing
3236 -- and move on to the next record. }}
3237 IF (l_demand_expected_time IS NULL) THEN
3238 IF (l_debug = 1) THEN
3239 print_debug('1.4 - Unable to crossdock WDD record since demand expected time is NULL');
3240 END IF;
3241 GOTO next_record;
3242 END IF;
3243 IF (l_debug = 1) THEN
3244 print_debug('1.4 - Demand expected time: => ' ||
3245 TO_CHAR(l_demand_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
3246 END IF;
3247 l_progress := '150';
3248
3249 -- Get the time interval values for the crossdock criteria.
3250 -- Time intervals will be defined using the function NUMTODSINTERVAL
3251 -- Crossdock Window Time Interval
3252 l_xdock_window_interval := NUMTODSINTERVAL
3253 (g_crossdock_criteria_tb(l_crossdock_criteria_id).window_interval,
3254 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_uom);
3255 IF (l_debug = 1) THEN
3256 print_debug('1.4 - Crossdock Window: ' ||
3257 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_interval || ' ' ||
3258 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_uom);
3259 END IF;
3260 -- Buffer Time Interval
3261 -- The buffer time interval and UOM should either both be NULL or not NULL.
3262 l_buffer_interval := NUMTODSINTERVAL
3263 (NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_interval, 0),
3264 NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_uom, 'HOUR'));
3265 IF (l_debug = 1) THEN
3266 print_debug('1.4 - Buffer Time: ' ||
3267 g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_interval || ' ' ||
3268 g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_uom);
3269 END IF;
3270 -- Order Processing Time Interval
3271 -- The order processing time interval and UOM should either both be NULL or not NULL.
3272 l_processing_interval := NUMTODSINTERVAL
3273 (NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_interval, 0),
3274 NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_uom, 'HOUR'));
3275 IF (l_debug = 1) THEN
3276 print_debug('1.4 - Order Processing Time: ' ||
3277 g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_interval || ' ' ||
3278 g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_uom);
3279 END IF;
3280 -- Past Due Time Interval
3281 -- The past due time interval and UOM should either both be NULL or not NULL.
3282 l_past_due_interval := NUMTODSINTERVAL
3283 (NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).past_due_interval, 0),
3284 NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).past_due_uom, 'HOUR'));
3285 IF (l_debug = 1) THEN
3286 print_debug('1.4 - Past Due Time: ' ||
3287 g_crossdock_criteria_tb(l_crossdock_criteria_id).past_due_interval || ' ' ||
3288 g_crossdock_criteria_tb(l_crossdock_criteria_id).past_due_uom);
3289 END IF;
3290 -- Set the variable to the past due time value.
3291 -- If this value is NULL, then that means we do not restrict past due supplies no matter
3292 -- how far in the past their expected time is.
3293 l_past_due_time := g_crossdock_criteria_tb(l_crossdock_criteria_id).past_due_interval;
3294
3295 -- If a dock appointment for the demand does not exist and the crossdock criteria
3296 -- allows rescheduling of the demand for anytime on the expected ship date, set the
3297 -- appropriate crossdock time window interval.
3298 -- {{
3299 -- Test for a WDD demand where a dock appointment does not exist and demand rescheduling
3300 -- is allowed. }}
3301 IF (NOT l_demand_dock_exists AND
3302 g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_demand_reschedule_flag = 1 AND
3303 l_demand_expected_time >= SYSDATE) THEN
3304 -- Demand can be scheduled anytime on the expected ship date so use 12:00AM to calculate
3305 -- the crossdock window start time and 11:59PM to calculate the crossdock window
3306 -- end time. Note this will yield a time interval of 24 hours plus the crossdock window
3307 -- time interval.
3308 l_xdock_start_time := TRUNC(l_demand_expected_time) -
3309 (l_processing_interval + l_buffer_interval + l_xdock_window_interval);
3310 l_xdock_end_time := TO_DATE(TO_CHAR(TRUNC(l_demand_expected_time), 'DD-MON-YYYY') ||
3311 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS') -
3312 (l_processing_interval + l_buffer_interval);
3313 ELSIF (l_demand_expected_time < SYSDATE) THEN
3314 -- For demand that is expected to ship out in the past, consider it as ready to ship
3315 -- out anytime on the current date. Ideally someone should go back to modify the
3316 -- scheduled ship date for these demand lines.
3317 l_xdock_start_time := TRUNC(SYSDATE) -
3318 (l_processing_interval + l_buffer_interval + l_xdock_window_interval);
3319 l_xdock_end_time := TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'DD-MON-YYYY') ||
3320 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS') -
3321 (l_processing_interval + l_buffer_interval);
3322 ELSE
3323 -- Demand cannot be rescheduled so just use the expected ship date to calculate
3324 -- the crossdock window start and end times for valid supplies to crossdock
3325 l_xdock_start_time := l_demand_expected_time -
3326 (l_processing_interval + l_buffer_interval + l_xdock_window_interval);
3327 l_xdock_end_time := l_demand_expected_time -
3328 (l_processing_interval + l_buffer_interval);
3329 END IF;
3330 IF (l_debug = 1) THEN
3331 print_debug('1.4 - Crossdock start time: => ' ||
3332 TO_CHAR(l_xdock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
3333 print_debug('1.4 - Crossdock end time: ===> ' ||
3334 TO_CHAR(l_xdock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
3335 END IF;
3336 l_progress := '160';
3337
3338 -- Section 2: Crossdocking existing high level reservations
3339 -- For the current demand line, query to see if any existing high level reservations
3340 -- exist. If they do, we should try to detail those first.
3341 -- 2.1 - Query for and lock existing high level reservations for the demand line.
3342 -- - If a reservation cannot be locked, do not pick up the record for crossdocking.
3343 -- 2.2 - Check if the supply line on reservation is valid for crossdocking.
3344 -- - Supply source type must be allowed on the crossdock criteria.
3345 -- - Supply expected receipt time must lie within the crossdock time window.
3346 -- 2.3 - Lock the supply line record(s). Check that the UOM on the supply and
3347 -- reservation match if UOM integrity is Yes. If cross project allocation is not
3348 -- allowed and the org is PJM enabled, make sure the project and task values
3349 -- on the supply line matches the demand.
3350 -- 2.4 - Crossdock detail the reservation and update the demand and supply line records.
3351 -- 2.5 - After processing through all existing reservations, check the prior reservations
3352 -- only flag on the picking batch. If 'Y', we are done with the current demand line.
3353 -- 2.6 - If quantity still remains on the WDD to be crossdocked, see how much reservable
3354 -- quantity on the demand is actually available for crossdocking.
3355
3356 -- 2.1 - Query for and lock existing high level reservations for the demand line.
3357 -- - If a reservation cannot be locked, do not pick up the record for crossdocking.
3358 -- {{
3359 -- Test for WDD demand lines with existing high level non-inventory reservations.
3360 -- The possible supply source types for these reservations are:
3361 -- Purchase Order
3362 -- Internal Requisition
3363 -- ASN
3364 -- In Transit Shipment
3365 -- In Receiving }}
3366 -- {{
3367 -- Test where an existing reservation is already locked. This record should not be
3368 -- picked up for crossdocking. }}
3369 IF (l_debug = 1) THEN
3370 print_debug('2.1 - Query for existing high level reservations for the demand line');
3371 END IF;
3372 -- Initialize the table we are fetching records into.
3373 l_existing_rsvs_tb.DELETE;
3374 BEGIN
3375 OPEN existing_rsvs_cursor;
3376 FETCH existing_rsvs_cursor BULK COLLECT INTO l_existing_rsvs_tb;
3377 CLOSE existing_rsvs_cursor;
3378 EXCEPTION
3379 WHEN OTHERS THEN
3380 IF (l_debug = 1) THEN
3381 print_debug('2.1 - Exception retrieving the existing reservations');
3382 END IF;
3383 GOTO after_existing_rsvs;
3384 --RAISE fnd_api.g_exc_unexpected_error;
3385 END;
3386 l_progress := '170';
3387
3388 -- Loop through the existing reservations and try to crossdock them
3389 l_rsv_index := l_existing_rsvs_tb.FIRST;
3390 LOOP
3391 -- If no existing reservations were found, exit out of loop.
3392 IF (l_existing_rsvs_tb.COUNT = 0) THEN
3393 IF (l_debug = 1) THEN
3394 print_debug('2.1 - No existing reservations to crossdock');
3395 END IF;
3396 EXIT;
3397 END IF;
3398
3399 -- Retrieve necessary parameters for the supply line from the current reservation
3400 l_rsv_id := l_existing_rsvs_tb(l_rsv_index).reservation_id;
3401 l_rsv_qty := l_existing_rsvs_tb(l_rsv_index).reservation_quantity;
3402 l_rsv_uom_code := l_existing_rsvs_tb(l_rsv_index).reservation_uom_code;
3403 l_rsv_qty2 := l_existing_rsvs_tb(l_rsv_index).secondary_reservation_quantity;
3404 l_rsv_uom_code2 := l_existing_rsvs_tb(l_rsv_index).secondary_uom_code;
3405 l_rsv_prim_qty := l_existing_rsvs_tb(l_rsv_index).primary_reservation_quantity;
3406 l_rsv_prim_uom_code := l_existing_rsvs_tb(l_rsv_index).primary_uom_code;
3407 l_supply_type_id := l_existing_rsvs_tb(l_rsv_index).supply_source_type_id;
3408 l_supply_header_id := l_existing_rsvs_tb(l_rsv_index).supply_source_header_id;
3409 l_supply_line_id := l_existing_rsvs_tb(l_rsv_index).supply_source_line_id;
3410 l_supply_line_detail_id := l_existing_rsvs_tb(l_rsv_index).supply_source_line_detail;
3411 IF (l_debug = 1) THEN
3412 print_debug('2.1 - Reservation ID: ========> ' || l_rsv_id);
3413 print_debug('2.1 - Reservation Quantity: ==> ' || l_rsv_qty || ' ' ||
3414 l_rsv_uom_code);
3415 print_debug('2.1 - Reservation Quantity2: => ' || l_rsv_qty2 || ' ' ||
3416 l_rsv_uom_code2);
3417 print_debug('2.1 - Reservation Prim Qty: ==> ' || l_rsv_prim_qty || ' ' ||
3418 l_rsv_prim_uom_code);
3419 print_debug('2.1 - Supply source type ID: => ' || l_supply_type_id);
3420 print_debug('2.1 - Supply header ID: ======> ' || l_supply_header_id);
3421 print_debug('2.1 - Supply line ID: ========> ' || l_supply_line_id);
3422 print_debug('2.1 - Supply line detail ID: => ' || l_supply_line_detail_id);
3423 END IF;
3424 l_progress := '180';
3425
3426 -- Make sure the primary UOM code on the reservation matches the one for the item.
3427 -- This error condition should not come about but if it does, just skip this
3428 -- reservation and go to the next one.
3429 IF (l_primary_uom_code <> l_rsv_prim_uom_code) THEN
3430 IF (l_debug = 1) THEN
3431 print_debug('2.1 - Item and reservation primary UOM codes do not match!');
3432 END IF;
3433 GOTO next_reservation;
3434 END IF;
3435 l_progress := '190';
3436
3437 -- 2.2 - Check if the supply line on reservation is valid for crossdocking.
3438 -- - Supply source type must be allowed on the crossdock criteria.
3439 -- - Supply expected receipt time must lie within the crossdock time window.
3440 -- Valid supplies:
3441 -- 1 - Purchase Order
3442 -- 7 - Internal Requisition
3443 -- 25 - ASN
3444 -- 26 - In Transit Shipment
3445 -- 27 - In Receiving
3446 IF (l_debug = 1) THEN
3447 print_debug('2.2 - Check if the supply line on reservation is valid for crossdocking');
3448 END IF;
3449
3450 -- Set the appropriate Crossdock Planned Supply source code. This uses a different
3451 -- set of lookup values compared to the reservations supply source codes.
3452 IF (l_supply_type_id = 1) THEN
3453 -- PO
3454 l_supply_src_code := G_PLAN_SUP_PO_APPR;
3455 ELSIF (l_supply_type_id = 7) THEN
3456 -- Internal Requisition
3457 l_supply_src_code := G_PLAN_SUP_REQ;
3458 ELSIF (l_supply_type_id = 25) THEN
3459 -- ASN
3460 l_supply_src_code := G_PLAN_SUP_ASN;
3461 ELSIF (l_supply_type_id = 26) THEN
3462 -- In Transit Shipment
3463 l_supply_src_code := G_PLAN_SUP_INTR;
3464 ELSIF (l_supply_type_id = 27) THEN
3465 -- In Receiving
3466 l_supply_src_code := G_PLAN_SUP_RCV;
3467 ELSE
3468 -- Invalid supply for crossdocking.
3469 -- {{
3470 -- For prior existing reservations that are not supported for crossdocking (WIP),
3471 -- make sure we do not try to crossdock them. }}
3472 GOTO next_reservation;
3473 END IF;
3474 IF (l_debug = 1) THEN
3475 print_debug('2.2 - Crossdock Supply Source Code: => ' || l_supply_src_code);
3476 END IF;
3477 l_progress := '200';
3478
3479 -- Supply source type must be allowed on the crossdock criteria.
3480 -- Check if the supply line tied to the reservation is valid for crossdocking
3481 -- based on the valid supply types allowed for the crossdock criteria.
3482 -- {{
3483 -- Test for existing reservations for valid supply types to crossdock which are
3484 -- not allowed on the crossdock criteria. Processing should stop and the next
3485 -- existing reservation should be considered for crossdocking. }}
3486 IF (NOT WMS_XDOCK_UTILS_PVT.Is_Eligible_Supply_Source
3487 (p_criterion_id => l_crossdock_criteria_id,
3488 p_source_code => l_supply_src_code)) THEN
3489 -- Supply line on reservation is not valid source for crossdocking
3490 IF (l_debug = 1) THEN
3491 print_debug('2.2 - Supply line on reservation is not valid source for crossdocking');
3492 END IF;
3493 GOTO next_reservation;
3494 END IF;
3495 l_progress := '210';
3496
3497 -- Supply expected receipt time must lie within the crossdock time window.
3498 -- Check if the supply line tied to the reservation is valid for crossdocking
3499 -- based on the crossdock window for the crossdock criteria.
3500 IF (l_debug = 1) THEN
3501 print_debug('2.2 - Determine the expected receipt time for the supply line');
3502 END IF;
3503 IF (l_supply_type_id <> 27) THEN
3504 -- For supply types that are not In Receiving, call the Get_Expected_Time
3505 -- API to determine the expected receipt time
3506 Get_Expected_Time
3507 (p_source_type_id => l_supply_type_id,
3508 p_source_header_id => l_supply_header_id,
3509 p_source_line_id => l_supply_line_id,
3510 p_source_line_detail_id => l_supply_line_detail_id,
3511 p_supply_or_demand => G_SRC_TYPE_SUP,
3512 p_crossdock_criterion_id => l_crossdock_criteria_id,
3513 x_return_status => x_return_status,
3514 x_msg_count => x_msg_count,
3515 x_msg_data => x_msg_data,
3516 x_dock_start_time => l_dock_start_time,
3517 x_dock_mean_time => l_dock_mean_time,
3518 x_dock_end_time => l_dock_end_time,
3519 x_expected_time => l_supply_expected_time);
3520
3521 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
3522 IF (l_debug = 1) THEN
3523 print_debug('2.2 - Success returned from Get_Expected_Time API');
3524 END IF;
3525 ELSE
3526 IF (l_debug = 1) THEN
3527 print_debug('2.2 - Failure returned from Get_Expected_Time API');
3528 END IF;
3529 GOTO next_reservation;
3530 --RAISE fnd_api.g_exc_error;
3531 END IF;
3532 -- Use this value to determine if a dock appointment for the supply line exists.
3533 -- There is a parameter on the crossdock criteria to decide if we should schedule
3534 -- supply anytime on the expected receipt date if no dock appointment exists.
3535 IF (l_dock_start_time IS NOT NULL) THEN
3536 l_supply_dock_exists := TRUE;
3537 ELSE
3538 l_supply_dock_exists := FALSE;
3539 END IF;
3540 ELSE
3541 -- In Receiving supply will just use SYSDATE as the expected receipt time
3542 l_supply_expected_time := SYSDATE;
3543 -- For In Receiving, dock appointments do not apply since the material is already
3544 -- received. However, set this variable to be TRUE so that the expected receipt time
3545 -- for the supply is not rescheduled for anytime on the expected receipt date.
3546 l_supply_dock_exists := TRUE;
3547 END IF;
3548 -- Do not crossdock the supply line on the reservation if an expected receipt
3549 -- time cannot be determined.
3550 -- {{
3551 -- If an expected receipt time for the supply line on an existing reservation
3552 -- cannot be determined, skip processing and move on to the next existing reservation. }}
3553 IF (l_supply_expected_time IS NULL) THEN
3554 IF (l_debug = 1) THEN
3555 print_debug('2.2 - Unable to crossdock reservation since supply expected time is NULL');
3556 END IF;
3557 GOTO next_reservation;
3558 END IF;
3559 IF (l_debug = 1) THEN
3560 print_debug('2.2 - Supply expected time: => ' ||
3561 TO_CHAR(l_supply_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
3562 END IF;
3563 l_progress := '220';
3564
3565 -- See if the supply lies within the crossdock time window.
3566 -- If a dock appointment for the supply does not exist and the crossdock criteria
3567 -- allows rescheduling of the supply for anytime on the expected receipt date, set the
3568 -- appropriate logic to determine if the supply is valid.
3569 -- {{
3570 -- Test for a supply line on an existing reservation that does not have a dock appointment
3571 -- and supply reschedule is allowed. }}
3572 -- {{
3573 -- Test for a supply line on an existing reservation lying within the crossdock window. }}
3574 -- {{
3575 -- Test for a supply line on an existing reservation not lying within the crossdock
3576 -- window. In this case, we cannot crossdock the existing reservation so just move
3577 -- on to the next one. }}
3578 IF ((NOT l_supply_dock_exists AND
3579 g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_supply_reschedule_flag = 1 AND
3580 l_supply_expected_time BETWEEN TRUNC(l_xdock_start_time) AND
3581 TO_DATE(TO_CHAR(TRUNC(l_xdock_end_time), 'DD-MON-YYYY') ||
3582 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS'))
3583 OR (l_supply_expected_time BETWEEN l_xdock_start_time AND l_xdock_end_time)) THEN
3584 -- Supply is valid for crossdocking based on crossdock time window
3585 IF (l_debug = 1) THEN
3586 print_debug('2.2 - Supply line is within the crossdock window');
3587 END IF;
3588 ELSE
3589 -- Supply is not valid for crossdocking so skip to the next existing
3590 -- reservation to crossdock
3591 IF (l_debug = 1) THEN
3592 print_debug('2.2 - Supply line is not within the crossdock window');
3593 END IF;
3594 GOTO next_reservation;
3595 END IF;
3596 l_progress := '230';
3597
3598 -- 2.3 - Lock the supply line record(s). Check that the UOM on the supply and
3599 -- reservation match if UOM integrity is Yes. If cross project allocation is not
3600 -- allowed and the org is PJM enabled, make sure the project and task values
3601 -- on the supply line matches the demand.
3602
3603 -- Based on the UOM integrity flag, decide if we should pick up the supply line record(s)
3604 -- only if the UOM matches the one on the reservation.
3605 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1) THEN
3606 l_supply_uom_code := l_existing_rsvs_tb(l_rsv_index).reservation_uom_code;
3607 ELSE
3608 l_supply_uom_code := NULL;
3609 END IF;
3610 IF (l_debug = 1) THEN
3611 print_debug('2.3 - UOM code the supply line should match to: ' || l_supply_uom_code);
3612 END IF;
3613
3614 -- The cursors to lock the supply lines take a UOM code as input to deal with UOM integrity.
3615 -- {{
3616 -- Test a crossdock criteria where UOM integrity is 'Y'. The UOM on the reservation
3617 -- and supply line must match. Test both cases where it does and does not match. If it
3618 -- doesn't match, then we should stop processing and move on to the next reservation. }}
3619 -- {{
3620 -- Test for a PJM org where cross project allocation is not allowed. For an existing
3621 -- reservation, if the demand and supply lines have different project and task values, the
3622 -- reservation should not be crossdocked. Test this for all types of supply lines.}}
3623 -- {{
3624 -- Test for a PJM org where cross project allocation is not allowed. For an existing
3625 -- reservation, if the supply line has multiple project/task values on the distribution
3626 -- level (PO, ASN, Int Req), the reservation should not be crossdocked.}}
3627 -- {{
3628 -- Test for a PJM org where cross project allocation is not allowed. For an existing
3629 -- reservation with a supply of type Intransit Shipment, the reservation should be skipped
3630 -- and not crossdocked.}}
3631 IF (l_debug = 1) THEN
3632 print_debug('2.3 - Lock and validate the supply line record(s): ' || l_supply_type_id);
3633 END IF;
3634 IF (l_supply_type_id = 1) THEN
3635 -- PO
3636 BEGIN
3637 OPEN lock_po_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
3638 FETCH lock_po_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
3639 IF (lock_po_record%NOTFOUND) THEN
3640 -- If a record is not found, do not error out. This could mean that the
3641 -- UOM on the supply did not match the reservation and UOM integrity is 'Y'.
3642 -- This could also mean that the project and task on the supply line did not
3643 -- match the demand and the org is PJM enabled and cross project allocation is
3644 -- not allowed. Skip this reservation and try to crossdock the next one.
3645 IF (l_debug = 1) THEN
3646 print_debug('2.3 - Supply record not found. UOM/project/task values do not match');
3647 END IF;
3648 CLOSE lock_po_record;
3649 GOTO next_reservation;
3650 END IF;
3651 CLOSE lock_po_record;
3652 EXCEPTION
3653 WHEN OTHERS THEN
3654 IF (l_debug = 1) THEN
3655 print_debug('2.3 - Could not lock the PO supply line record');
3656 END IF;
3657 -- If we cannot lock the supply line, do not error out. Just go to the
3658 -- next existing reservation and try to crossdock that.
3659 GOTO next_reservation;
3660 END;
3661 ELSIF (l_supply_type_id = 7) THEN
3662 -- Internal Requisition
3663 BEGIN
3664 OPEN lock_intreq_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
3665 -- Multiple records could be returned from this cursor. We only care about existence.
3666 FETCH lock_intreq_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
3667 IF (lock_intreq_record%NOTFOUND) THEN
3668 -- If a record is not found, do not error out. This could mean that the
3669 -- UOM on the supply did not match the reservation and UOM integrity is 'Y'.
3670 -- This could also mean that the project and task on the supply line did not
3671 -- match the demand and the org is PJM enabled and cross project allocation is
3672 -- not allowed. Skip this reservation and try to crossdock the next one.
3673 IF (l_debug = 1) THEN
3674 print_debug('2.3 - Supply record not found. UOM/project/task values do not match');
3675 END IF;
3676 CLOSE lock_intreq_record;
3677 GOTO next_reservation;
3678 END IF;
3679 CLOSE lock_intreq_record;
3680 EXCEPTION
3681 WHEN OTHERS THEN
3682 IF (l_debug = 1) THEN
3683 print_debug('2.3 - Could not lock the Internal Req supply line record');
3684 END IF;
3685 -- If we cannot lock the supply line, do not error out. Just go to the
3686 -- next existing reservation and try to crossdock that.
3687 GOTO next_reservation;
3688 END;
3689 ELSIF (l_supply_type_id = 25) THEN
3690 -- ASN
3691 BEGIN
3692 OPEN lock_asn_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
3693 FETCH lock_asn_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
3694 IF (lock_asn_record%NOTFOUND) THEN
3695 -- If a record is not found, do not error out. This could mean that the
3696 -- UOM on the supply did not match the reservation and UOM integrity is 'Y'.
3697 -- This could also mean that the project and task on the supply line did not
3698 -- match the demand and the org is PJM enabled and cross project allocation is
3699 -- not allowed. Skip this reservation and try to crossdock the next one.
3700 IF (l_debug = 1) THEN
3701 print_debug('2.3 - Supply record not found. UOM/project/task values do not match');
3702 END IF;
3703 CLOSE lock_asn_record;
3704 GOTO next_reservation;
3705 END IF;
3706 CLOSE lock_asn_record;
3707 EXCEPTION
3708 WHEN OTHERS THEN
3709 IF (l_debug = 1) THEN
3710 print_debug('2.3 - Could not lock the ASN supply line record');
3711 END IF;
3712 -- If we cannot lock the supply line, do not error out. Just go to the
3713 -- next existing reservation and try to crossdock that.
3714 GOTO next_reservation;
3715 END;
3716 ELSIF (l_supply_type_id = 26) THEN
3717 -- In Transit Shipment
3718 BEGIN
3719 OPEN lock_intship_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
3720 FETCH lock_intship_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
3721 IF (lock_intship_record%NOTFOUND) THEN
3722 -- If a record is not found, do not error out. This could mean that the
3723 -- UOM on the supply did not match the reservation and UOM integrity is 'Y'.
3724 -- This could also mean that the org is PJM enabled, cross project allocation
3725 -- is not allowed, and the demand project/task is not null. In Transit Shipments
3726 -- going to a PJM org will only be allowed for common stock (NULL) project/task.
3727 -- Skip this reservation and try to crossdock the next one.
3728 IF (l_debug = 1) THEN
3729 print_debug('2.3 - Supply record not found. UOM/project/task values do not match');
3730 END IF;
3731 CLOSE lock_intship_record;
3732 GOTO next_reservation;
3733 END IF;
3734 CLOSE lock_intship_record;
3735 EXCEPTION
3736 WHEN OTHERS THEN
3737 IF (l_debug = 1) THEN
3738 print_debug('2.3 - Could not lock the In Transit Shipment supply line record');
3739 END IF;
3740 -- If we cannot lock the supply line, do not error out. Just go to the
3741 -- next existing reservation and try to crossdock that.
3742 GOTO next_reservation;
3743 END;
3744 ELSIF (l_supply_type_id = 27) THEN
3745 -- In Receiving
3746 -- Initialize the table we are fetching records into.
3747 l_rcv_lines_tb.DELETE;
3748 BEGIN
3749 OPEN lock_receiving_lines(l_supply_uom_code, l_rsv_prim_qty,
3750 l_demand_project_id, l_demand_task_id);
3751 FETCH lock_receiving_lines BULK COLLECT INTO l_rcv_lines_tb;
3752 -- If no valid receiving lines are found, do not error out. Skip this
3753 -- reservation and try to crossdock the next one. This means that there were no
3754 -- valid MOLs found that matched either the UOM (if UOM integrity is 'Y') or the
3755 -- project/task (if cross project allocation is not allowed for a PJM org).
3756 IF (l_rcv_lines_tb.COUNT = 0) THEN
3757 IF (l_debug = 1) THEN
3758 print_debug('2.3 - No valid receiving supply lines found');
3759 END IF;
3760 CLOSE lock_receiving_lines;
3761 GOTO next_reservation;
3762 END IF;
3763 CLOSE lock_receiving_lines;
3764 EXCEPTION
3765 WHEN OTHERS THEN
3766 IF (l_debug = 1) THEN
3767 print_debug('2.3 - Could not lock the Receiving supply line records');
3768 END IF;
3769 -- If we cannot lock the supply lines, do not error out. Just go to the
3770 -- next existing reservation and try to crossdock that.
3771 GOTO next_reservation;
3772 END;
3773 ELSE
3774 -- Invalid supply for crossdocking.
3775 GOTO next_reservation;
3776 END IF; -- End locking supply line(s) from different source types
3777 IF (l_debug = 1) THEN
3778 print_debug('2.3 - Successfully locked and validated the supply line record(s)');
3779 print_debug('2.3 - Supply UOM Code: ===> ' || l_supply_uom_code);
3780 print_debug('2.3 - Supply Project ID: => ' || l_supply_project_id);
3781 print_debug('2.3 - Supply Task ID: ====> ' || l_supply_task_id);
3782 END IF;
3783 l_progress := '240';
3784
3785 -- 2.4 - Crossdock detail the reservation and update the demand and supply line records.
3786 IF (l_debug = 1) THEN
3787 print_debug('2.4 - Crossdock detail the relevant records: RSV, WDD, supply');
3788 END IF;
3789 l_supply_index := NVL(l_rcv_lines_tb.FIRST, 1);
3790
3791 -- Loop through the valid supply lines to fulfill the existing reservation.
3792 -- For non-receiving supply types, there will only be one such supply line to use.
3793 -- For Receiving supply type, there is at least one valid MOL to fulfill the reservation.
3794 -- {{
3795 -- For supply line(s) of In Receiving type, test that the MOL's are looped through
3796 -- properly until they are all exhausted, reservation is fulfilled, or WDD quantity is
3797 -- is completely fulfilled. }}
3798 LOOP
3799 -- Define a savepoint so if an exception occurs while updating database records such as
3800 -- WDD, RSV, or MOL, we need to rollback the changes and goto the next WDD record
3801 -- to crossdock. Put this inside the supply lines loop so if one supply line
3802 -- is crossdocked successfully but another one errors out, we can still crossdock
3803 -- the first one. Multiple supply lines are only possible for Receiving supply type.
3804 SAVEPOINT Existing_Reservation_sp;
3805
3806 -- Initialize the variables to store the original WDD values in case
3807 -- we need to rollback the changes to local PLSQL data structures
3808 l_split_wdd_index := NULL;
3809 l_split_delivery_index := NULL;
3810 l_orig_wdd_values_rec := NULL;
3811 l_xdocked_wdd_index := NULL;
3812
3813 -- Set the supply UOM code to the UOM of the current MOL for receiving supply type.
3814 -- For non-receiving supply types, there is only one line and the supply UOM code
3815 -- has already been retrieved when locking the supply line record.
3816 IF (l_supply_type_id = 27) THEN
3817 l_mol_header_id := l_rcv_lines_tb(l_supply_index).header_id;
3818 l_mol_line_id := l_rcv_lines_tb(l_supply_index).line_id;
3819 l_mol_qty := l_rcv_lines_tb(l_supply_index).quantity;
3820 l_supply_uom_code := l_rcv_lines_tb(l_supply_index).uom_code;
3821 l_mol_prim_qty := l_rcv_lines_tb(l_supply_index).primary_quantity;
3822 l_mol_qty2 := l_rcv_lines_tb(l_supply_index).secondary_quantity;
3823 l_mol_uom_code2 := l_rcv_lines_tb(l_supply_index).secondary_uom_code;
3824 l_supply_project_id := l_rcv_lines_tb(l_supply_index).project_id;
3825 l_supply_task_id := l_rcv_lines_tb(l_supply_index).task_id;
3826 l_mol_lpn_id := l_rcv_lines_tb(l_supply_index).lpn_id;
3827 ELSE
3828 l_mol_line_id := NULL;
3829 END IF;
3830 l_progress := '250';
3831
3832 -- Convert the WDD qty to the UOM on the supply line.
3833 IF (l_debug = 1) THEN
3834 print_debug('2.4 - Current supply UOM code to convert to: ' || l_supply_uom_code);
3835 END IF;
3836 -- Retrieve the conversion rate for the item/from UOM/to UOM combination.
3837 -- {{
3838 -- Test that the WDD quantity is converted properly to the UOM on the supply line. }}
3839 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
3840 l_demand_uom_code, l_supply_uom_code);
3841 IF (l_conversion_rate < 0) THEN
3842 IF (l_debug = 1) THEN
3843 print_debug('2.4 - Error while obtaining UOM conversion rate for WDD qty');
3844 END IF;
3845 -- Rollback any db changes that might have occurred (currently none).
3846 ROLLBACK TO Existing_Reservation_sp;
3847 -- Process the next existing reservation record.
3848 GOTO next_reservation;
3849 END IF;
3850 -- Round the converted quantity to the standard precision
3851 l_wdd_txn_qty := ROUND(l_conversion_rate * l_demand_qty, l_conversion_precision);
3852 IF (l_debug = 1) THEN
3853 print_debug('2.4 - WDD qty: =====> ' || l_demand_qty || ' ' || l_demand_uom_code);
3854 print_debug('2.4 - WDD txn qty: => ' || l_wdd_txn_qty || ' ' || l_supply_uom_code);
3855 END IF;
3856 l_progress := '260';
3857
3858 -- Convert the RSV qty to the UOM on the supply line.
3859 -- Retrieve the conversion rate for the item/from UOM/to UOM combination.
3860 -- {{
3861 -- Test that the RSV quantity is converted properly to the UOM on the supply line. }}
3862 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
3863 l_rsv_uom_code, l_supply_uom_code);
3864 IF (l_conversion_rate < 0) THEN
3865 IF (l_debug = 1) THEN
3866 print_debug('2.4 - Error while obtaining UOM conversion rate for RSV qty');
3867 END IF;
3868 -- Rollback any db changes that might have occurred (currently none).
3869 ROLLBACK TO Existing_Reservation_sp;
3870 -- Process the next existing reservation record.
3871 GOTO next_reservation;
3872 END IF;
3873 -- Round the converted quantity to the standard precision
3874 l_rsv_txn_qty := ROUND(l_conversion_rate * l_rsv_qty, l_conversion_precision);
3875 IF (l_debug = 1) THEN
3876 print_debug('2.4 - RSV qty: =====> ' || l_rsv_qty || ' ' || l_rsv_uom_code);
3877 print_debug('2.4 - RSV txn qty: => ' || l_rsv_txn_qty || ' ' || l_supply_uom_code);
3878 END IF;
3879 l_progress := '270';
3880
3881 -- For receiving supply types, multiple MOL's comprise the supply line source.
3882 IF (l_supply_type_id = 27) THEN
3883 IF (l_debug = 1) THEN
3884 print_debug('2.4 - MOL qty: =====> ' || l_mol_qty || ' ' || l_supply_uom_code);
3885 END IF;
3886 ELSE
3887 -- For non-receiving supply types, just set this to be equal to the RSV txn qty.
3888 -- We assume that there is more than enough quantity on the supply to fulfill
3889 -- the reservation otherwise it should not have been created. This variable is
3890 -- set here for calculating the ATD qty.
3891 l_mol_qty := l_rsv_txn_qty;
3892 END IF;
3893
3894 -- Calculate the Available to Detail quantity.
3895 -- {{
3896 -- Test that the available to detail quantity is calculated properly,
3897 -- i.e. is lower than WDD, RSV, and MOL qty, and is an integer value if
3898 -- UOM integrity = 'Y'. }}
3899 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1) THEN
3900 -- UOM Integrity is 'Yes'
3901 l_atd_qty := LEAST(FLOOR(l_wdd_txn_qty), FLOOR(l_rsv_txn_qty), FLOOR(l_mol_qty));
3902 ELSE
3903 -- UOM Integrity is 'No'
3904 l_atd_qty := LEAST(l_wdd_txn_qty, l_rsv_txn_qty, l_mol_qty);
3905 END IF;
3906 IF (l_debug = 1) THEN
3907 print_debug('2.4 - Available to detail qty: ' || l_atd_qty || ' ' ||
3908 l_supply_uom_code);
3909 END IF;
3910 -- If the ATD qty is 0, then goto the next reservation to crossdock.
3911 -- This is possible if the UOM integrity flag is 'Y' and the resultant quantities
3912 -- were floored to 0.
3913 -- {{
3914 -- Test for ATD qty = 0. This can come about if UOM integrity is Yes and the
3915 -- demand, reservation or supply line gets floored to 0. }}
3916 IF (l_atd_qty = 0) THEN
3917 IF (l_debug = 1) THEN
3918 print_debug('2.4 - No available qty to detail for this reservation');
3919 END IF;
3920 -- Rollback any db changes that might have occurred (currently none).
3921 ROLLBACK TO Existing_Reservation_sp;
3922 -- Process the next existing reservation record.
3923 GOTO next_reservation;
3924 END IF;
3925 l_progress := '280';
3926
3927 -- Convert l_atd_qty to the primary UOM
3928 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
3929 l_supply_uom_code, l_primary_uom_code);
3930 IF (l_conversion_rate < 0) THEN
3931 IF (l_debug = 1) THEN
3932 print_debug('2.4 - Error while obtaining primary UOM conversion rate for ATD qty');
3933 END IF;
3934 -- Rollback any db changes that might have occurred (currently none).
3935 ROLLBACK TO Existing_Reservation_sp;
3936 -- Process the next existing reservation record.
3937 GOTO next_reservation;
3938 END IF;
3939 -- Round the converted quantity to the standard precision
3940 l_atd_prim_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
3941 IF (l_debug = 1) THEN
3942 print_debug('2.4 - ATD qty in primary UOM: => ' || l_atd_prim_qty || ' ' ||
3943 l_primary_uom_code);
3944 END IF;
3945 l_progress := '290';
3946
3947 -- Store the original WDD values in case of rollback where we need
3948 -- to clean up the local PLSQL data structures
3949 l_orig_wdd_values_rec.requested_quantity :=
3950 p_wsh_release_table(l_wdd_index).requested_quantity;
3951 l_orig_wdd_values_rec.requested_quantity2 :=
3952 p_wsh_release_table(l_wdd_index).requested_quantity2;
3953 l_orig_wdd_values_rec.released_status :=
3954 p_wsh_release_table(l_wdd_index).released_status;
3955 l_orig_wdd_values_rec.move_order_line_id :=
3956 p_wsh_release_table(l_wdd_index).move_order_line_id;
3957
3958 -- Crossdock the WDD record, splitting it if necessary.
3959 IF (l_debug = 1) THEN
3960 print_debug('2.4 - Call the Crossdock_WDD API to crossdock/split the WDD');
3961 END IF;
3962 Crossdock_WDD
3963 (p_log_prefix => '2.4 - ',
3964 p_crossdock_type => G_CRT_TYPE_PLAN,
3965 p_batch_id => p_batch_id,
3966 p_wsh_release_table => p_wsh_release_table,
3967 p_trolin_delivery_ids => p_trolin_delivery_ids,
3968 p_del_detail_id => p_del_detail_id,
3969 l_wdd_index => l_wdd_index,
3970 l_debug => l_debug,
3971 l_inventory_item_id => l_inventory_item_id,
3972 l_wdd_txn_qty => l_wdd_txn_qty,
3973 l_atd_qty => l_atd_qty,
3974 l_atd_wdd_qty => l_atd_wdd_qty,
3975 l_atd_wdd_qty2 => l_atd_wdd_qty2,
3976 l_supply_uom_code => l_supply_uom_code,
3977 l_demand_uom_code => l_demand_uom_code,
3978 l_demand_uom_code2 => l_demand_uom_code2,
3979 l_conversion_rate => l_conversion_rate,
3980 l_conversion_precision => l_conversion_precision,
3981 l_demand_line_detail_id => l_demand_line_detail_id,
3982 l_index => l_index,
3983 l_detail_id_tab => l_detail_id_tab,
3984 l_action_prms => l_action_prms,
3985 l_action_out_rec => l_action_out_rec,
3986 l_split_wdd_id => l_split_wdd_id,
3987 l_detail_info_tab => l_detail_info_tab,
3988 l_in_rec => l_in_rec,
3989 l_out_rec => l_out_rec,
3990 l_mol_line_id => l_mol_line_id,
3991 l_split_wdd_index => l_split_wdd_index,
3992 l_split_delivery_index => l_split_delivery_index,
3993 l_split_wdd_rel_rec => l_split_wdd_rel_rec,
3994 l_allocation_method => l_allocation_method,
3995 l_demand_qty => l_demand_qty,
3996 l_demand_qty2 => l_demand_qty2,
3997 l_demand_atr_qty => l_demand_atr_qty,
3998 l_xdocked_wdd_index => l_xdocked_wdd_index,
3999 l_supply_type_id => l_supply_type_id,
4000 x_return_status => x_return_status,
4001 x_msg_count => x_msg_count,
4002 x_msg_data => x_msg_data,
4003 x_error_code => l_error_code
4004 );
4005
4006 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4007 IF (l_debug = 1) THEN
4008 print_debug('2.4 - Error returned from Crossdock_WDD API: '
4009 || x_return_status);
4010 END IF;
4011 --RAISE fnd_api.g_exc_error;
4012 -- If an exception occurs while modifying a database record, rollback the changes
4013 -- and just go to the next WDD record or reservation to crossdock.
4014 ROLLBACK TO Existing_Reservation_sp;
4015 -- We need to also rollback changes done to local PLSQL data structures
4016 IF (l_split_wdd_index IS NOT NULL) THEN
4017 p_wsh_release_table.DELETE(l_split_wdd_index);
4018 END IF;
4019 IF (l_split_delivery_index IS NOT NULL) THEN
4020 p_del_detail_id.DELETE(l_split_delivery_index);
4021 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
4022 END IF;
4023 IF (l_xdocked_wdd_index IS NOT NULL) THEN
4024 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
4025 END IF;
4026 p_wsh_release_table(l_wdd_index).requested_quantity :=
4027 l_orig_wdd_values_rec.requested_quantity;
4028 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
4029 l_orig_wdd_values_rec.requested_quantity2;
4030 p_wsh_release_table(l_wdd_index).released_status :=
4031 l_orig_wdd_values_rec.released_status;
4032 p_wsh_release_table(l_wdd_index).move_order_line_id :=
4033 l_orig_wdd_values_rec.move_order_line_id;
4034
4035 -- Skip to the next WDD record or reservation to crossdock
4036 IF (l_error_code = 'UOM') THEN
4037 GOTO next_reservation;
4038 ELSE -- l_error_code = 'DB'
4039 GOTO next_record;
4040 END IF;
4041 ELSE
4042 IF (l_debug = 1) THEN
4043 print_debug('2.4 - Successfully crossdocked/split the WDD record');
4044 END IF;
4045
4046
4047 if p_simulation_mode = 'Y' THEN
4048
4049 x_wp_crossdock_tbl(l_wdd_index).delivery_detail_id := p_wsh_release_table(l_wdd_index).delivery_detail_id;
4050
4051 if l_split_flag = 'Y' then
4052
4053 x_wp_crossdock_tbl(l_wdd_index).crossdock_qty := l_atd_wdd_qty;
4054
4055 print_debug('In Case of Splitting the crossdocked qty is '||x_wp_crossdock_tbl(l_wdd_index).crossdock_qty);
4056
4057 ELSE
4058
4059 x_wp_crossdock_tbl(l_wdd_index).crossdock_qty := l_wdd_txn_qty;
4060
4061 print_debug('Crossdock Quantity without SPlit '||x_wp_crossdock_tbl(l_wdd_index).crossdock_qty);
4062
4063 end if;
4064 END IF;
4065
4066 END IF;
4067 l_progress := '300';
4068
4069 if p_simulation_mode ='Y' THEN -- Ajith
4070
4071 null;
4072
4073 else
4074 -- Crossdock the RSV record, splitting it if necessary
4075 IF (l_debug = 1) THEN
4076 print_debug('2.4 - Call the Crossdock_RSV API to crossdock/split the RSV');
4077 END IF;
4078
4079
4080
4081 Crossdock_RSV
4082 (p_log_prefix => '2.4 - ',
4083 p_crossdock_type => G_CRT_TYPE_PLAN,
4084 l_debug => l_debug,
4085 l_inventory_item_id => l_inventory_item_id,
4086 l_rsv_txn_qty => l_rsv_txn_qty,
4087 l_atd_qty => l_atd_qty,
4088 l_atd_rsv_qty => l_atd_rsv_qty,
4089 l_atd_rsv_qty2 => l_atd_rsv_qty2,
4090 l_atd_prim_qty => l_atd_prim_qty,
4091 l_supply_uom_code => l_supply_uom_code,
4092 l_rsv_uom_code => l_rsv_uom_code,
4093 l_rsv_uom_code2 => l_rsv_uom_code2,
4094 l_primary_uom_code => l_primary_uom_code,
4095 l_conversion_rate => l_conversion_rate,
4096 l_conversion_precision => l_conversion_precision,
4097 l_original_rsv_rec => l_original_rsv_rec,
4098 l_rsv_id => l_rsv_id,
4099 l_to_rsv_rec => l_to_rsv_rec,
4100 l_split_wdd_id => l_split_wdd_id,
4101 l_crossdock_criteria_id => l_crossdock_criteria_id,
4102 l_demand_expected_time => l_demand_expected_time,
4103 l_supply_expected_time => l_supply_expected_time,
4104 l_original_serial_number => l_original_serial_number,
4105 l_split_rsv_id => l_split_rsv_id,
4106 l_rsv_qty => l_rsv_qty,
4107 l_rsv_qty2 => l_rsv_qty2,
4108 l_to_serial_number => l_to_serial_number,
4109 l_supply_type_id => l_supply_type_id,
4110 x_return_status => x_return_status,
4111 x_msg_count => x_msg_count,
4112 x_msg_data => x_msg_data,
4113 x_error_code => l_error_code
4114 );
4115
4116 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4117 IF (l_debug = 1) THEN
4118 print_debug('2.4 - Error returned from Crossdock_RSV API: '
4119 || x_return_status);
4120 END IF;
4121 --RAISE fnd_api.g_exc_error;
4122 -- If an exception occurs while modifying a database record, rollback the changes
4123 -- and just go to the next WDD record or reservation to crossdock.
4124 ROLLBACK TO Existing_Reservation_sp;
4125 -- We need to also rollback changes done to local PLSQL data structures
4126 IF (l_split_wdd_index IS NOT NULL) THEN
4127 p_wsh_release_table.DELETE(l_split_wdd_index);
4128 END IF;
4129 IF (l_split_delivery_index IS NOT NULL) THEN
4130 p_del_detail_id.DELETE(l_split_delivery_index);
4131 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
4132 END IF;
4133 IF (l_xdocked_wdd_index IS NOT NULL) THEN
4134 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
4135 END IF;
4136 p_wsh_release_table(l_wdd_index).requested_quantity :=
4137 l_orig_wdd_values_rec.requested_quantity;
4138 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
4139 l_orig_wdd_values_rec.requested_quantity2;
4140 p_wsh_release_table(l_wdd_index).released_status :=
4141 l_orig_wdd_values_rec.released_status;
4142 p_wsh_release_table(l_wdd_index).move_order_line_id :=
4143 l_orig_wdd_values_rec.move_order_line_id;
4144
4145 -- Skip to the next WDD record or reservation to crossdock
4146 IF (l_error_code = 'UOM') THEN
4147 GOTO next_reservation;
4148 ELSE -- l_error_code = 'DB'
4149 GOTO next_record;
4150 END IF;
4151 ELSE
4152 IF (l_debug = 1) THEN
4153 print_debug('2.4 - Successfully crossdocked/split the RSV record');
4154 END IF;
4155 END IF;
4156 l_progress := '310';
4157
4158
4159 -- Crossdock and split the MOL supply line if necessary
4160 IF (l_mol_line_id IS NOT NULL) THEN
4161 IF (l_debug = 1) THEN
4162 print_debug('2.4 - Call the Crossdock_MOL API to crossdock/split the MOL: '
4163 || l_mol_line_id);
4164 END IF;
4165 Crossdock_MOL
4166 (p_log_prefix => '2.4 - ',
4167 p_crossdock_type => G_CRT_TYPE_PLAN,
4168 l_debug => l_debug,
4169 l_inventory_item_id => l_inventory_item_id,
4170 l_mol_qty => l_mol_qty,
4171 l_mol_qty2 => l_mol_qty2,
4172 l_atd_qty => l_atd_qty,
4173 l_atd_mol_qty2 => l_atd_mol_qty2,
4174 l_supply_uom_code => l_supply_uom_code,
4175 l_mol_uom_code2 => l_mol_uom_code2,
4176 l_conversion_rate => l_conversion_rate,
4177 l_conversion_precision => l_conversion_precision,
4178 l_mol_prim_qty => l_mol_prim_qty,
4179 l_atd_prim_qty => l_atd_prim_qty,
4180 l_split_wdd_id => l_split_wdd_id,
4181 l_mol_header_id => l_mol_header_id,
4182 l_mol_line_id => l_mol_line_id,
4183 l_supply_atr_qty => l_supply_atr_qty,
4184 l_demand_type_id => l_demand_type_id,
4185 l_wip_entity_id => l_wip_entity_id,
4186 l_operation_seq_num => l_operation_seq_num,
4187 l_repetitive_schedule_id => l_repetitive_schedule_id,
4188 l_wip_supply_type => l_wip_supply_type,
4189 l_xdocked_wdd_index => l_xdocked_wdd_index,
4190 l_detail_info_tab => l_detail_info_tab,
4191 l_wdd_index => l_wdd_index,
4192 l_split_wdd_index => l_split_wdd_index,
4193 p_wsh_release_table => p_wsh_release_table,
4194 l_supply_type_id => l_supply_type_id,
4195 x_return_status => x_return_status,
4196 x_msg_count => x_msg_count,
4197 x_msg_data => x_msg_data,
4198 x_error_code => l_error_code,
4199 x_new_mol_id => l_new_mol_id --9695544
4200 );
4201
4202 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4203 IF (l_debug = 1) THEN
4204 print_debug('2.4 - Error returned from Crossdock_MOL API: '
4205 || x_return_status);
4206 END IF;
4207 --RAISE fnd_api.g_exc_error;
4208 -- If an exception occurs while modifying a database record, rollback the changes
4209 -- and just go to the next WDD record or reservation to crossdock.
4210 ROLLBACK TO Existing_Reservation_sp;
4211 -- We need to also rollback changes done to local PLSQL data structures
4212 IF (l_split_wdd_index IS NOT NULL) THEN
4213 p_wsh_release_table.DELETE(l_split_wdd_index);
4214 END IF;
4215 IF (l_split_delivery_index IS NOT NULL) THEN
4216 p_del_detail_id.DELETE(l_split_delivery_index);
4217 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
4218 END IF;
4219 IF (l_xdocked_wdd_index IS NOT NULL) THEN
4220 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
4221 END IF;
4222 p_wsh_release_table(l_wdd_index).requested_quantity :=
4223 l_orig_wdd_values_rec.requested_quantity;
4224 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
4225 l_orig_wdd_values_rec.requested_quantity2;
4226 p_wsh_release_table(l_wdd_index).released_status :=
4227 l_orig_wdd_values_rec.released_status;
4228 p_wsh_release_table(l_wdd_index).move_order_line_id :=
4229 l_orig_wdd_values_rec.move_order_line_id;
4230
4231 -- Skip to the next WDD record or reservation to crossdock
4232 IF (l_error_code = 'UOM') THEN
4233 GOTO next_reservation;
4234 ELSE -- l_error_code = 'DB'
4235 GOTO next_record;
4236 END IF;
4237 ELSE
4238 IF (l_debug = 1) THEN
4239 print_debug('2.4 - Successfully crossdocked/split the MOL record');
4240 END IF;
4241 END IF;
4242
4243 -- Store this LPN in the crossdocked LPNs table so we can call the pre_generate
4244 -- API later on for the entire set of LPN's instead of once for each MOL that
4245 -- is crossdocked.
4246 IF (NOT l_crossdocked_lpns_tb.EXISTS(l_mol_lpn_id)) THEN
4247 l_crossdocked_lpns_tb(l_mol_lpn_id) := TRUE;
4248 IF (l_debug = 1) THEN
4249 print_debug('2.4 - Successfully stored the crossdocked LPN: ' || l_mol_lpn_id);
4250 END IF;
4251 END IF;
4252 l_progress := '320';
4253
4254 END IF; -- End of l_mol_line_id IS NOT NULL for receiving supply type
4255
4256
4257 -- Exit out of loop if the WDD line has been fully crossdocked or the
4258 -- reservation has been fully consumed
4259 IF (p_wsh_release_table(l_wdd_index).released_status = 'S' OR l_rsv_qty = 0) THEN
4260 EXIT;
4261 END IF;
4262 end if; --Ajith ---Check whether it is correct
4263 -- Exit out of loop for non-receiving supply types.
4264 IF (l_supply_type_id <> 27) THEN
4265 EXIT;
4266 END IF;
4267
4268 -- Exit when all supply lines (receiving MOL's for this case) have been considered
4269 EXIT WHEN l_supply_index = l_rcv_lines_tb.LAST;
4270 l_supply_index := l_rcv_lines_tb.NEXT(l_supply_index);
4271 END LOOP; -- End looping through supply line(s)
4272 IF (l_supply_type_id = 27 AND l_rcv_lines_tb.COUNT > 0) THEN
4273 -- Clear the receiving lines table if the supply type is Receiving
4274 l_rcv_lines_tb.DELETE;
4275 END IF;
4276 l_progress := '330';
4277
4278 -- Exit out of existing reservations loop if the WDD line has been fully crossdocked.
4279 -- There is no need to consider anymore existing reservations.
4280 IF (p_wsh_release_table(l_wdd_index).released_status = 'S') THEN
4281 EXIT;
4282 END IF;
4283 -- {{
4284 -- Test for existing reservation cases where RSV qty >, =, < WDD qty. }}
4285
4286 <<next_reservation>>
4287 EXIT WHEN l_rsv_index = l_existing_rsvs_tb.LAST;
4288 l_rsv_index := l_existing_rsvs_tb.NEXT(l_rsv_index);
4289 END LOOP; -- End looping through existing reservations
4290 l_progress := '340';
4291
4292 -- 2.5 - After processing through all existing reservations, check the prior reservations
4293 -- only flag on the picking batch. If 'Y', we are done with the current demand line.
4294 -- {{
4295 -- Test for picking batch where we only want to allocate against existing reservations.
4296 -- If that is the case, stop crossdocking after trying to crossdock existing reservations. }}
4297 <<after_existing_rsvs>>
4298 IF (l_debug = 1) THEN
4299 print_debug('2.5 - Check the allocate against existing reservations only flag');
4300 print_debug('2.5 - Existing RSVs Only Flag: ==> ' || l_existing_rsvs_only);
4301 print_debug('2.5 - WDD line released status: => ' ||
4302 p_wsh_release_table(l_wdd_index).released_status);
4303 END IF;
4304 IF (l_existing_rsvs_only = 'Y' OR
4305 p_wsh_release_table(l_wdd_index).released_status = 'S') THEN
4306 GOTO next_record;
4307 END IF;
4308 l_progress := '350';
4309
4310 -- 2.6 - If quantity still remains on the WDD to be crossdocked, see how much reservable
4311 -- quantity on the demand is actually available for crossdocking.
4312 -- This API will return quantity in the primary UOM.
4313 IF (l_debug = 1) THEN
4314 print_debug('2.6 - Calculate the ATR qty on the demand line for crossdocking');
4315 END IF;
4316 INV_RESERVATION_AVAIL_PVT.Available_demand_to_reserve
4317 (p_api_version_number => 1.0,
4318 p_init_msg_lst => fnd_api.g_false,
4319 x_return_status => x_return_status,
4320 x_msg_count => x_msg_count,
4321 x_msg_data => x_msg_data,
4322 p_primary_uom_code => l_primary_uom_code,
4323 p_demand_source_type_id => l_demand_type_id,
4324 p_demand_source_header_id => l_demand_so_header_id,
4325 p_demand_source_line_id => l_demand_line_id,
4326 p_demand_source_line_detail => l_demand_line_detail_id,
4327 p_project_id => l_demand_project_id,
4328 p_task_id => l_demand_task_id,
4329 x_qty_available_to_reserve => l_demand_atr_prim_qty,
4330 x_qty_available => l_demand_available_qty);
4331
4332 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4333 IF (l_debug = 1) THEN
4334 print_debug('2.6 - Error returned from available_demand_to_reserve API: '
4335 || x_return_status);
4336 END IF;
4337 GOTO next_record;
4338 --RAISE fnd_api.g_exc_error;
4339 END IF;
4340 IF (l_debug = 1) THEN
4341 print_debug('2.6 - Available qty to reserve (primary) for demand: ' ||
4342 l_demand_atr_prim_qty || ' ' || l_primary_uom_code);
4343 END IF;
4344 l_progress := '360';
4345
4346 -- Check how much quantity is available to be crossdocked.
4347 -- {{
4348 -- Test for case where the WDD line, after considering existing reservations, does not
4349 -- have any reservable quantity. This line cannot be crossdocked and we should move
4350 -- on to the next record. }}
4351 IF (l_demand_atr_prim_qty <= 0) THEN
4352 GOTO next_record;
4353 ELSE
4354 -- Convert the ATR primary quantity to the UOM on the WDD demand line
4355 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
4356 l_primary_uom_code, l_demand_uom_code);
4357 IF (l_conversion_rate < 0) THEN
4358 IF (l_debug = 1) THEN
4359 print_debug('2.6 - Error while obtaining Primary UOM conversion rate for WDD');
4360 END IF;
4361 GOTO next_record;
4362 END IF;
4363 -- Round the converted quantity to the standard precision
4364 l_demand_atr_qty := ROUND(l_conversion_rate * l_demand_atr_prim_qty, l_conversion_precision);
4365 IF (l_debug = 1) THEN
4366 print_debug('2.6 - Available qty to reserve for demand: ' || l_demand_atr_qty ||
4367 ' ' || l_demand_uom_code);
4368 END IF;
4369 l_progress := '370';
4370
4371 -- Instead of splitting the WDD record here with the ATR quantity, just keep track
4372 -- of that qty and use it later on when determining the available to detail qty.
4373 -- In this way, we can minimize the amount of WDD splitting, doing it only when
4374 -- absolutely necessary.
4375 END IF;
4376
4377 -- Section 3: Build the set of available supply lines for the demand
4378 -- 3.1 - Query and cache the available supply source types for crossdocking based on the
4379 -- current crossdock criteria.
4380 -- 3.2 - For each supply source type, retrieve the available supply lines.
4381 -- 3.3 - For each supply line retrieved, determine the expected receipt time.
4382 -- 3.4 - Insert the available supply lines into the global temp table.
4383 -- 3.5 - Retrieve all of the supply lines that fall within the crossdock window and
4384 -- store it in the shopping basket table. If prioritize documents, order this
4385 -- by the source type.
4386 -- 3.6 - Sort the supply lines in the shopping basket table based on the crossdocking
4387 -- goals.
4388
4389 -- 3.1 - Query and cache the available supply source types for crossdocking based on the
4390 -- current crossdock criteria.
4391 IF (l_debug = 1) THEN
4392 print_debug('3.1 - Query and cache the available supply source types for crossdocking');
4393 END IF;
4394 IF (NOT l_supply_src_types_tb.EXISTS(l_crossdock_criteria_id)) THEN
4395 BEGIN
4396 OPEN supply_src_types_cursor;
4397 FETCH supply_src_types_cursor BULK COLLECT INTO
4398 l_supply_src_types_tb(l_crossdock_criteria_id);
4399 CLOSE supply_src_types_cursor;
4400 EXCEPTION
4401 WHEN OTHERS THEN
4402 IF (l_debug = 1) THEN
4403 print_debug('3.1 - Exception retrieving the eligible supply source types');
4404 END IF;
4405 GOTO next_record;
4406 --RAISE fnd_api.g_exc_unexpected_error;
4407 END;
4408 IF (l_debug = 1) THEN
4409 print_debug('3.1 - Successfully retrieved the eligible supply source types for criteria: '
4410 || l_crossdock_criteria_id);
4411 END IF;
4412 END IF;
4413 l_progress := '380';
4414
4415 -- 3.2 - For each supply source type, retrieve the available supply lines.
4416 IF (l_debug = 1) THEN
4417 print_debug('3.2 - For each supply source type, retrieve the available supply lines');
4418 END IF;
4419
4420 -- Set a savepoint in case an error occurs while inserting supply line records
4421 -- into the global temp table.
4422 SAVEPOINT Supply_Lines_sp;
4423
4424 FOR i IN 1 .. l_supply_src_types_tb(l_crossdock_criteria_id).COUNT LOOP
4425 -- Store the current supply source code
4426 l_supply_src_code := l_supply_src_types_tb(l_crossdock_criteria_id)(i);
4427
4428 -- Retrieve the available supply lines for the current supply source type and item
4429 -- combination if it has not been done already. Here we do not care about project/task
4430 -- and will retrieve all of the valid supply lines for the org/item regardless of the
4431 -- project/task. Each demand line could have a different project/task to match to. That
4432 -- logic should be done in the get_supply_lines cursor when building the shopping cart
4433 -- table.
4434 -- {{
4435 -- Test to make sure that if a supply source type for a given item has already been
4436 -- retrieved, do not requery the information again. }}
4437 IF ((l_src_types_retrieved_tb.EXISTS(l_inventory_item_id) AND
4438 NOT l_src_types_retrieved_tb(l_inventory_item_id).EXISTS(l_supply_src_code)) OR
4439 NOT l_src_types_retrieved_tb.EXISTS(l_inventory_item_id)) THEN
4440
4441 IF (l_debug = 1) THEN
4442 IF (l_supply_src_code = G_PLAN_SUP_PO_APPR) THEN
4443 print_debug('3.2 - Supply source type to retrieve: Approved PO');
4444 ELSIF (l_supply_src_code = G_PLAN_SUP_ASN) THEN
4445 print_debug('3.2 - Supply source type to retrieve: ASN');
4446 ELSIF (l_supply_src_code = G_PLAN_SUP_REQ) THEN
4447 print_debug('3.2 - Supply source type to retrieve: Internal Requisition');
4448 ELSIF (l_supply_src_code = G_PLAN_SUP_INTR) THEN
4449 print_debug('3.2 - Supply source type to retrieve: In Transit Shipment');
4450 ELSIF (l_supply_src_code = G_PLAN_SUP_RCV) THEN
4451 print_debug('3.2 - Supply source type to retrieve: In Receiving');
4452 ELSE
4453 print_debug('3.2 - Supply source type to retrieve: INVALID SUPPLY!');
4454 END IF;
4455 END IF;
4456
4457 -- Initialize the tables we are BULK fetching into
4458 l_header_id_tb.DELETE;
4459 l_line_id_tb.DELETE;
4460 l_line_detail_id_tb.DELETE;
4461 l_dock_start_time_tb.DELETE;
4462 l_dock_mean_time_tb.DELETE;
4463 l_dock_end_time_tb.DELETE;
4464 l_expected_time_tb.DELETE;
4465 l_quantity_tb.DELETE;
4466 l_uom_code_tb.DELETE;
4467 l_primary_quantity_tb.DELETE;
4468 l_secondary_quantity_tb.DELETE;
4469 l_secondary_uom_code_tb.DELETE;
4470 l_project_id_tb.DELETE;
4471 l_task_id_tb.DELETE;
4472 l_lpn_id_tb.DELETE;
4473
4474 -- Bulk collect the supply line cursors into the PLSQL tables based on
4475 -- the current crossdock supply source type.
4476 IF (l_supply_src_code = G_PLAN_SUP_PO_APPR) THEN
4477 -- PO
4478 BEGIN
4479 OPEN po_approved_lines;
4480 FETCH po_approved_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
4481 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb, l_primary_quantity_tb,
4482 l_secondary_quantity_tb, l_secondary_uom_code_tb,
4483 l_project_id_tb, l_task_id_tb, l_lpn_id_tb;
4484 CLOSE po_approved_lines;
4485 EXCEPTION
4486 WHEN OTHERS THEN
4487 IF (l_debug = 1) THEN
4488 print_debug('3.2 - Could not retrieve the PO supply lines');
4489 END IF;
4490 -- If we cannot retrieve the available supply lines, do not error out.
4491 -- Just go to the next record and try to crossdock that.
4492 -- Rollback any db changes that might have occurred (currently none).
4493 ROLLBACK TO Supply_Lines_sp;
4494 GOTO next_record;
4495 END;
4496 l_supply_type_id := 1;
4497 ELSIF (l_supply_src_code = G_PLAN_SUP_ASN) THEN
4498 -- ASN
4499 BEGIN
4500 OPEN po_asn_lines;
4501 FETCH po_asn_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
4502 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb, l_primary_quantity_tb,
4503 l_secondary_quantity_tb, l_secondary_uom_code_tb,
4504 l_project_id_tb, l_task_id_tb, l_lpn_id_tb;
4505 CLOSE po_asn_lines;
4506 EXCEPTION
4507 WHEN OTHERS THEN
4508 IF (l_debug = 1) THEN
4509 print_debug('3.2 - Could not retrieve the ASN supply lines');
4510 END IF;
4511 -- If we cannot retrieve the available supply lines, do not error out.
4512 -- Just go to the next record and try to crossdock that.
4513 -- Rollback any db changes that might have occurred (currently none).
4514 ROLLBACK TO Supply_Lines_sp;
4515 GOTO next_record;
4516 END;
4517 l_supply_type_id := 25;
4518 ELSIF (l_supply_src_code = G_PLAN_SUP_REQ) THEN
4519 -- Internal Requisition
4520 BEGIN
4521 OPEN internal_req_lines;
4522 FETCH internal_req_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
4523 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb, l_primary_quantity_tb,
4524 l_secondary_quantity_tb, l_secondary_uom_code_tb,
4525 l_project_id_tb, l_task_id_tb, l_lpn_id_tb;
4526 CLOSE internal_req_lines;
4527 EXCEPTION
4528 WHEN OTHERS THEN
4529 IF (l_debug = 1) THEN
4530 print_debug('3.2 - Could not retrieve the Internal Req supply lines');
4531 END IF;
4532 -- If we cannot retrieve the available supply lines, do not error out.
4533 -- Just go to the next record and try to crossdock that.
4534 -- Rollback any db changes that might have occurred (currently none).
4535 ROLLBACK TO Supply_Lines_sp;
4536 GOTO next_record;
4537 END;
4538 l_supply_type_id := 7;
4539 ELSIF (l_supply_src_code = G_PLAN_SUP_INTR) THEN
4540 -- In Transit Shipment
4541 BEGIN
4542 OPEN intship_lines;
4543 FETCH intship_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
4544 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb, l_primary_quantity_tb,
4545 l_secondary_quantity_tb, l_secondary_uom_code_tb,
4546 l_project_id_tb, l_task_id_tb, l_lpn_id_tb;
4547 CLOSE intship_lines;
4548 EXCEPTION
4549 WHEN OTHERS THEN
4550 IF (l_debug = 1) THEN
4551 print_debug('3.2 - Could not retrieve the In Transit Shipment supply lines');
4552 END IF;
4553 -- If we cannot retrieve the available supply lines, do not error out.
4554 -- Just go to the next record and try to crossdock that.
4555 -- Rollback any db changes that might have occurred (currently none).
4556 ROLLBACK TO Supply_Lines_sp;
4557 GOTO next_record;
4558 END;
4559 l_supply_type_id := 26;
4560 ELSIF (l_supply_src_code = G_PLAN_SUP_RCV) THEN
4561 -- In Receiving
4562 BEGIN
4563 OPEN in_receiving_lines;
4564 FETCH in_receiving_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
4565 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb, l_primary_quantity_tb,
4566 l_secondary_quantity_tb, l_secondary_uom_code_tb,
4567 l_project_id_tb, l_task_id_tb, l_lpn_id_tb;
4568 CLOSE in_receiving_lines;
4569 EXCEPTION
4570 WHEN OTHERS THEN
4571 IF (l_debug = 1) THEN
4572 print_debug('3.2 - Could not retrieve the In Receiving supply lines');
4573 END IF;
4574 -- If we cannot retrieve the available supply lines, do not error out.
4575 -- Just go to the next record and try to crossdock that.
4576 -- Rollback any db changes that might have occurred (currently none).
4577 ROLLBACK TO Supply_Lines_sp;
4578 GOTO next_record;
4579 END;
4580 l_supply_type_id := 27;
4581 ELSE
4582 -- Invalid supply type for crossdocking
4583 -- Rollback any db changes that might have occurred (currently none).
4584 ROLLBACK TO Supply_Lines_sp;
4585 GOTO next_record;
4586 END IF; -- End retrieving supply lines for different supply source types
4587 IF (l_debug = 1) THEN
4588 IF (l_supply_src_code = G_PLAN_SUP_PO_APPR) THEN
4589 print_debug('3.2 - Successfully retrieved ' || l_header_id_tb.COUNT ||
4590 ' available line(s) for Approved PO');
4591 ELSIF (l_supply_src_code = G_PLAN_SUP_ASN) THEN
4592 print_debug('3.2 - Successfully retrieved ' || l_header_id_tb.COUNT ||
4593 ' available line(s) for ASN');
4594 ELSIF (l_supply_src_code = G_PLAN_SUP_REQ) THEN
4595 print_debug('3.2 - Successfully retrieved ' || l_header_id_tb.COUNT ||
4596 ' available line(s) for Internal Requisition');
4597 ELSIF (l_supply_src_code = G_PLAN_SUP_INTR) THEN
4598 print_debug('3.2 - Successfully retrieved ' || l_header_id_tb.COUNT ||
4599 ' available line(s) for In Transit Shipment');
4600 ELSIF (l_supply_src_code = G_PLAN_SUP_RCV) THEN
4601 print_debug('3.2 - Successfully retrieved ' || l_header_id_tb.COUNT ||
4602 ' available line(s) for In Receiving');
4603 END IF;
4604 END IF;
4605 ELSE
4606 -- Supply source type has already been retrieved
4607 IF (l_debug = 1) THEN
4608 IF (l_supply_src_code = G_PLAN_SUP_PO_APPR) THEN
4609 print_debug('3.2 - Supply source has already been retrieved: Approved PO');
4610 ELSIF (l_supply_src_code = G_PLAN_SUP_ASN) THEN
4611 print_debug('3.2 - Supply source has already been retrieved: ASN');
4612 ELSIF (l_supply_src_code = G_PLAN_SUP_REQ) THEN
4613 print_debug('3.2 - Supply source has already been retrieved: Internal Requisition');
4614 ELSIF (l_supply_src_code = G_PLAN_SUP_INTR) THEN
4615 print_debug('3.2 - Supply source has already been retrieved: In Transit Shipment');
4616 ELSIF (l_supply_src_code = G_PLAN_SUP_RCV) THEN
4617 print_debug('3.2 - Supply source has already been retrieved: In Receiving');
4618 END IF;
4619 END IF;
4620 END IF;
4621 l_progress := '390';
4622
4623 -- 3.3 - For each supply line retrieved, determine the expected receipt time.
4624 -- Do the logic in section 3.3 and 3.4 only if records are retrieved
4625 -- for the current supply source type.
4626 IF (l_header_id_tb.COUNT > 0) THEN
4627 IF (l_debug = 1) THEN
4628 print_debug('3.3 - For each supply line retrieved, calculate the expected receipt time');
4629 END IF;
4630 FOR j IN 1 .. l_header_id_tb.COUNT LOOP
4631 -- Call the Get_Expected_Time API if the supply type is not In Receiving
4632 IF (l_supply_type_id <> 27) THEN
4633 -- Do not pass the crossdock criteria ID since we want to be able to reuse
4634 -- the supply lines for other demand lines which might have different
4635 -- crossdock criteria values. If a dock appointment time is found, it will
4636 -- be passed in the output dock time variables.
4637 Get_Expected_Time
4638 (p_source_type_id => l_supply_type_id,
4639 p_source_header_id => l_header_id_tb(j),
4640 p_source_line_id => l_line_id_tb(j),
4641 p_source_line_detail_id => l_line_detail_id_tb(j),
4642 p_supply_or_demand => G_SRC_TYPE_SUP,
4643 p_crossdock_criterion_id => NULL,
4644 x_return_status => x_return_status,
4645 x_msg_count => x_msg_count,
4646 x_msg_data => x_msg_data,
4647 x_dock_start_time => l_dock_start_time_tb(j),
4648 x_dock_mean_time => l_dock_mean_time_tb(j),
4649 x_dock_end_time => l_dock_end_time_tb(j),
4650 x_expected_time => l_expected_time_tb(j));
4651
4652 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
4653 IF (l_debug = 1) THEN
4654 print_debug('3.3 - Success returned from Get_Expected_Time API');
4655 END IF;
4656 ELSE
4657 IF (l_debug = 1) THEN
4658 print_debug('3.3 - Failure returned from Get_Expected_Time API');
4659 END IF;
4660 -- Rollback any db changes that might have occurred (currently none).
4661 ROLLBACK TO Supply_Lines_sp;
4662 GOTO next_record;
4663 --RAISE fnd_api.g_exc_error;
4664 END IF;
4665 ELSE
4666 -- In Receiving supply types have an expected time of SYSDATE
4667 -- since it has already been received. Just set the dock expected times
4668 -- since this is what the Get_Expected_Time API would do if the crossdock
4669 -- criterion is not passed. We want to go against the 'dock' time as the exact
4670 -- time and not use the expected time (in case the 'Supply Reschedule Method' is used).
4671 l_dock_start_time_tb(j) := SYSDATE;
4672 l_dock_mean_time_tb(j) := SYSDATE;
4673 l_dock_end_time_tb(j) := SYSDATE;
4674 l_expected_time_tb(j) := NULL;
4675 END IF;
4676
4677 END LOOP; -- End looping through supply lines retrieved
4678 IF (l_debug = 1) THEN
4679 print_debug('3.3 - Finished calculating expected time for all supply lines');
4680 END IF;
4681 l_progress := '400';
4682
4683 -- 3.4 - Insert the available supply lines into the global temp table.
4684 -- {{
4685 -- Make sure the valid supply lines are properly inserted into the
4686 -- global temp table. }}
4687 IF (l_debug = 1) THEN
4688 print_debug('3.4 - Insert the available supply lines into the global temp table');
4689 END IF;
4690 BEGIN
4691 FORALL k IN 1 .. l_header_id_tb.COUNT
4692 INSERT INTO wms_xdock_pegging_gtmp
4693 (inventory_item_id,
4694 xdock_source_code,
4695 source_type_id,
4696 source_header_id,
4697 source_line_id,
4698 source_line_detail_id,
4699 dock_start_time,
4700 dock_mean_time,
4701 dock_end_time,
4702 expected_time,
4703 quantity,
4704 uom_code,
4705 primary_quantity,
4706 secondary_quantity,
4707 secondary_uom_code,
4708 project_id,
4709 task_id,
4710 lpn_id
4711 )
4712 VALUES
4713 (l_inventory_item_id,
4714 l_supply_src_code,
4715 l_supply_type_id,
4716 l_header_id_tb(k),
4717 l_line_id_tb(k),
4718 l_line_detail_id_tb(k),
4719 l_dock_start_time_tb(k),
4720 l_dock_mean_time_tb(k),
4721 l_dock_end_time_tb(k),
4722 l_expected_time_tb(k),
4723 l_quantity_tb(k),
4724 l_uom_code_tb(k),
4725 l_primary_quantity_tb(k),
4726 l_secondary_quantity_tb(k),
4727 l_secondary_uom_code_tb(k),
4728 l_project_id_tb(k),
4729 l_task_id_tb(k),
4730 l_lpn_id_tb(k)
4731 );
4732 EXCEPTION
4733 WHEN OTHERS THEN
4734 IF (l_debug = 1) THEN
4735 print_debug('3.4 - Error inserting available supply lines into temp table');
4736 END IF;
4737 --RAISE fnd_api.g_exc_error;
4738 -- If an exception occurs while inserting supply line records, just
4739 -- rollback the changes and go to the next WDD record to crossdock.
4740 ROLLBACK TO Supply_Lines_sp;
4741 GOTO next_record;
4742 END;
4743 IF (l_debug = 1) THEN
4744 print_debug('3.4 - Successfully inserted ' || l_header_id_tb.COUNT ||
4745 ' available supply lines into temp table');
4746 END IF;
4747 l_progress := '410';
4748
4749 -- Clear the PLSQL tables used once the data is inserted into the global temp table
4750 l_header_id_tb.DELETE;
4751 l_line_id_tb.DELETE;
4752 l_line_detail_id_tb.DELETE;
4753 l_dock_start_time_tb.DELETE;
4754 l_dock_mean_time_tb.DELETE;
4755 l_dock_end_time_tb.DELETE;
4756 l_expected_time_tb.DELETE;
4757 l_quantity_tb.DELETE;
4758 l_uom_code_tb.DELETE;
4759 l_primary_quantity_tb.DELETE;
4760 l_secondary_quantity_tb.DELETE;
4761 l_secondary_uom_code_tb.DELETE;
4762 l_project_id_tb.DELETE;
4763 l_task_id_tb.DELETE;
4764 l_lpn_id_tb.DELETE;
4765 END IF; -- END IF matches: IF (l_header_id_tb.COUNT > 0) THEN
4766
4767 -- Set the marker indicating we have retrieved the supply lines for the
4768 -- current source type and item. This value could already exist if the supply source
4769 -- type and item was retrieved previously. However it is okay to set this again.
4770 l_src_types_retrieved_tb(l_inventory_item_id)(l_supply_src_code) := TRUE;
4771 l_progress := '420';
4772
4773 END LOOP; -- End looping through eligible supply source types
4774
4775 -- 3.5 - Retrieve all of the supply lines that fall within the crossdock window and
4776 -- store it in the shopping basket table. If prioritize documents, order this
4777 -- by the source type.
4778 IF (l_debug = 1) THEN
4779 print_debug('3.5 - Retrieve all of the supply lines that are valid for crossdocking');
4780 END IF;
4781
4782 -- Iniitialize the shopping basket table which will store the valid supply lines
4783 -- for crossdocking to the current demand line.
4784 l_shopping_basket_tb.DELETE;
4785
4786 -- Initialize the available supply source types to retrieve
4787 l_po_sup := -1;
4788 l_asn_sup := -1;
4789 l_intreq_sup := -1;
4790 l_intship_sup := -1;
4791 l_rcv_sup := -1;
4792
4793 -- Initialize the supply document priority variables
4794 l_po_priority := 99;
4795 l_asn_priority := 99;
4796 l_intreq_priority := 99;
4797 l_intship_priority := 99;
4798 l_rcv_priority := 99;
4799
4800 -- Get the valid supply source types to retrieve.
4801 -- The supply source types are cached in the order of the document priority already.
4802 -- Just use the same index value for the document priority variable.
4803 FOR i IN 1 .. l_supply_src_types_tb(l_crossdock_criteria_id).COUNT LOOP
4804 IF (l_supply_src_types_tb(l_crossdock_criteria_id)(i) = G_PLAN_SUP_PO_APPR) THEN
4805 l_po_sup := G_PLAN_SUP_PO_APPR;
4806 l_po_priority := i;
4807 ELSIF (l_supply_src_types_tb(l_crossdock_criteria_id)(i) = G_PLAN_SUP_ASN) THEN
4808 l_asn_sup := G_PLAN_SUP_ASN;
4809 l_asn_priority := i;
4810 ELSIF (l_supply_src_types_tb(l_crossdock_criteria_id)(i) = G_PLAN_SUP_REQ) THEN
4811 l_intreq_sup := G_PLAN_SUP_REQ;
4812 l_intreq_priority := i;
4813 ELSIF (l_supply_src_types_tb(l_crossdock_criteria_id)(i) = G_PLAN_SUP_INTR) THEN
4814 l_intship_sup := G_PLAN_SUP_INTR;
4815 l_intship_priority := i;
4816 ELSIF (l_supply_src_types_tb(l_crossdock_criteria_id)(i) = G_PLAN_SUP_RCV) THEN
4817 l_rcv_sup := G_PLAN_SUP_RCV;
4818 l_rcv_priority := i;
4819 END IF;
4820 END LOOP;
4821
4822 -- If we do not need to prioritize documents, reset the supply document
4823 -- priority variables to the same default value
4824 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).prioritize_documents_flag = 2) THEN
4825 l_po_priority := 99;
4826 l_asn_priority := 99;
4827 l_intreq_priority := 99;
4828 l_intship_priority := 99;
4829 l_rcv_priority := 99;
4830 END IF;
4831
4832 -- Now get the valid supply lines for crossdocking and store it in the
4833 -- shopping basket table. Only pick up supply lines that match the project/task
4834 -- on the demand (if necessary).
4835 -- {{
4836 -- Make sure the supply lines are retrieved properly into the shopping basket table.
4837 -- Do this both with and without enforcing document priority. Also use various
4838 -- available supply types. }}
4839 BEGIN
4840 OPEN get_supply_lines
4841 (p_xdock_start_time => l_xdock_start_time,
4842 p_xdock_end_time => l_xdock_end_time,
4843 p_sup_resched_flag => g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_supply_reschedule_flag,
4844 p_sup_sched_method => g_crossdock_criteria_tb(l_crossdock_criteria_id).supply_schedule_method,
4845 p_crossdock_goal => g_crossdock_criteria_tb(l_crossdock_criteria_id).crossdock_goal,
4846 p_past_due_interval => l_past_due_interval,
4847 p_past_due_time => l_past_due_time,
4848 p_po_sup => l_po_sup,
4849 p_po_priority => l_po_priority,
4850 p_asn_sup => l_asn_sup,
4851 p_asn_priority => l_asn_priority,
4852 p_intreq_sup => l_intreq_sup,
4853 p_intreq_priority => l_intreq_priority,
4854 p_intship_sup => l_intship_sup,
4855 p_intship_priority => l_intship_priority,
4856 p_rcv_sup => l_rcv_sup,
4857 p_rcv_priority => l_rcv_priority,
4858 p_demand_prim_qty => l_demand_atr_prim_qty,
4859 p_project_id => l_demand_project_id,
4860 p_task_id => l_demand_task_id);
4861 FETCH get_supply_lines BULK COLLECT INTO l_shopping_basket_tb;
4862 CLOSE get_supply_lines;
4863 EXCEPTION
4864 WHEN OTHERS THEN
4865 IF (l_debug = 1) THEN
4866 print_debug('3.5 - Could not retrieve the valid supply lines for available source types');
4867 END IF;
4868 -- If we cannot retrieve the valid supply lines, do not error out.
4869 -- Just go to the next record and try to crossdock that.
4870 GOTO next_record;
4871 END;
4872 IF (l_debug = 1) THEN
4873 print_debug('3.5 - Successfully populated the shopping basket table with ' ||
4874 l_shopping_basket_tb.COUNT || ' crossdockable supply lines');
4875 END IF;
4876 l_progress := '430';
4877
4878 -- 3.6 - Sort the supply lines in the shopping basket table based on the crossdocking
4879 -- goals.
4880 -- For crossdock goals of Minimize Wait and Maximize Crossdock, the supply lines in the
4881 -- shopping basket have already been sorted.
4882 -- {{
4883 -- Test out the custom crossdock goal method of sorting the shopping basket lines.
4884 -- The not implemented stub version should just pass back the inputted shopping basket
4885 -- table without sorting them. }}
4886 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).crossdock_goal = G_CUSTOM_GOAL) THEN
4887 -- For each record in the shopping basket table, call the available to reserve API
4888 -- to determine how much quantity from each supply line is available for crossdocking.
4889 -- We need to do this since the custom logic might decide which supply lines to consume
4890 -- based on the reservable quantity (e.g. Best Fit SPQ type of logic).
4891 -- Do this only if the value is not available yet in the shopping basket supply record.
4892 IF (l_debug = 1) THEN
4893 print_debug('3.6 - Use custom logic to sort the supply lines');
4894 END IF;
4895
4896 FOR i IN 1 .. l_shopping_basket_tb.COUNT LOOP
4897
4898 IF (l_shopping_basket_tb(i).reservable_quantity IS NULL) THEN
4899 -- Reservable Quantity value has not been calculated yet for this supply.
4900 -- This API will return available to reserve quantity in the primary UOM.
4901 IF (l_debug = 1) THEN
4902 print_debug('3.6 - Call the Available_supply_to_reserve API');
4903 END IF;
4904 INV_RESERVATION_AVAIL_PVT.Available_supply_to_reserve
4905 (p_api_version_number => 1.0,
4906 p_init_msg_lst => fnd_api.g_false,
4907 x_return_status => x_return_status,
4908 x_msg_count => x_msg_count,
4909 x_msg_data => x_msg_data,
4910 p_organization_id => l_organization_id,
4911 p_item_id => l_inventory_item_id,
4912 p_supply_source_type_id => l_shopping_basket_tb(i).source_type_id,
4913 p_supply_source_header_id => l_shopping_basket_tb(i).source_header_id,
4914 p_supply_source_line_id => l_shopping_basket_tb(i).source_line_id,
4915 p_supply_source_line_detail => l_shopping_basket_tb(i).source_line_detail_id,
4916 p_project_id => l_shopping_basket_tb(i).project_id,
4917 p_task_id => l_shopping_basket_tb(i).task_id,
4918 x_qty_available_to_reserve => l_supply_atr_prim_qty,
4919 x_qty_available => l_supply_available_qty);
4920
4921 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4922 IF (l_debug = 1) THEN
4923 print_debug('3.6 - Error returned from available_supply_to_reserve API: '
4924 || x_return_status);
4925 END IF;
4926 -- Instead of erroring out and going to the next WDD record to crossdock,
4927 -- just delete the supply line from the shopping basket table. Shopping basket
4928 -- table can therefore be a sparsely populated table after running custom logic.
4929 l_shopping_basket_tb.DELETE(i);
4930 GOTO next_custom_supply;
4931 --GOTO next_record;
4932 --RAISE fnd_api.g_exc_error;
4933 END IF;
4934
4935 -- If the supply is 'In Receiving', the ATR qty returned is for all of receiving.
4936 -- Since we're working on a specific MOL supply line, we need to use a LEAST
4937 -- to get the min qty value.
4938 IF (l_shopping_basket_tb(i).source_type_id = 27) THEN
4939 l_supply_atr_prim_qty := LEAST(l_shopping_basket_tb(i).primary_quantity,
4940 l_supply_atr_prim_qty);
4941 END IF;
4942
4943 -- Convert the ATR primary quantity to the UOM on the supply line
4944 l_supply_uom_code := l_shopping_basket_tb(i).uom_code;
4945 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
4946 l_primary_uom_code, l_supply_uom_code);
4947 IF (l_conversion_rate < 0) THEN
4948 IF (l_debug = 1) THEN
4949 print_debug('3.6 - Error while obtaining Primary UOM conversion rate for supply line');
4950 END IF;
4951 -- Instead of erroring out and going to the next WDD record to crossdock,
4952 -- just delete the supply line from the shopping basket table. Shopping basket
4953 -- table can therefore be a sparsely populated table after running custom logic.
4954 l_shopping_basket_tb.DELETE(i);
4955 GOTO next_custom_supply;
4956 END IF;
4957 -- Round the converted quantity to the standard precision
4958 l_supply_atr_qty := ROUND(l_conversion_rate * l_supply_atr_prim_qty, l_conversion_precision);
4959 IF (l_debug = 1) THEN
4960 print_debug('3.6 - Supply line ATR qty: ' || l_supply_atr_qty || ' ' ||
4961 l_supply_uom_code);
4962 END IF;
4963
4964 ELSIF (l_shopping_basket_tb(i).reservable_quantity IS NOT NULL) THEN
4965 -- Reservable Quantity value has alraedy been calculated for this supply.
4966 l_supply_atr_qty := l_shopping_basket_tb(i).reservable_quantity;
4967 END IF;
4968
4969 -- Set the quantity field to be equal to the ATR quanitty for the current supply line
4970 -- record in the shopping basket. We do not want to set this value in
4971 -- the reservable_quantity column since this is also used to indicate if the supply line
4972 -- record has been locked already. Since we are not locking the supply line records yet
4973 -- here when using custom logic, we will make use of the quantity field instead.
4974 -- The custom API should make use of the quantity value instead when sorting the supply
4975 -- lines.
4976 l_shopping_basket_tb(i).quantity := l_supply_atr_qty;
4977
4978 <<next_custom_supply>>
4979 NULL; -- Need an executable statment for the branching label above
4980 END LOOP; -- End retrieving ATR quantity for all supply lines in shopping basket table
4981 -- At this stage, the shopping basket table will have the ATR quantity stamped on all of
4982 -- the records. The table can be sparse so the custom logic to sort the shopping basket
4983 -- must keep this in mind. This will be documented in the custom logic API.
4984 l_progress := '440';
4985
4986 -- Call the Custom logic to sort the shopping basket table.
4987 -- If the API is not implemented, the lines will not be sorted at all.
4988 -- {{
4989 -- Test that invalid custom logic to sort demand lines is caught. No sorting
4990 -- should be done if this is the case. }}
4991 IF (l_debug = 1) THEN
4992 print_debug('3.6 - Call the Sort_Supply_Lines API');
4993 END IF;
4994 WMS_XDOCK_CUSTOM_APIS_PUB.Sort_Supply_Lines
4995 (p_wdd_release_record => p_wsh_release_table(l_wdd_index),
4996 p_prioritize_documents => g_crossdock_criteria_tb(l_crossdock_criteria_id).prioritize_documents_flag,
4997 p_shopping_basket_tb => l_shopping_basket_tb,
4998 x_return_status => x_return_status,
4999 x_msg_count => x_msg_count,
5000 x_msg_data => x_msg_data,
5001 x_api_is_implemented => l_api_is_implemented,
5002 x_sorted_order_tb => l_sorted_order_tb);
5003
5004 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
5005 IF (l_debug = 1) THEN
5006 print_debug('3.6 - Success returned from Sort_Supply_Lines API');
5007 END IF;
5008 ELSE
5009 IF (l_debug = 1) THEN
5010 print_debug('3.6 - Failure returned from Sort_Supply_Lines API');
5011 END IF;
5012 -- In case of exception, do not error out. Just use whatever order the
5013 -- supply lines are in when the shopping basket table was created.
5014 --RAISE fnd_api.g_exc_error;
5015 l_sorted_order_tb.DELETE;
5016 END IF;
5017 l_progress := '450';
5018
5019 IF (NOT l_api_is_implemented) THEN
5020 IF (l_debug = 1) THEN
5021 print_debug('3.6 - Custom API is NOT implemented even though Custom Goal is selected!');
5022 END IF;
5023 ELSE
5024 IF (l_debug = 1) THEN
5025 print_debug('3.6 - Custom API is implemented so custom sorting logic is used');
5026 END IF;
5027 END IF;
5028
5029 -- Validate that the output l_sorted_order_tb is not larger in size than
5030 -- the shopping basket table and that values exist in l_sorted_order_tb.
5031 IF (l_debug = 1) THEN
5032 print_debug('3.6 - Rebuild the shopping basket table based on the sorting order returned');
5033 END IF;
5034 IF (l_sorted_order_tb.COUNT > l_shopping_basket_tb.COUNT OR
5035 l_sorted_order_tb.COUNT = 0) THEN
5036 -- Invalid condition from the custom logic API.
5037 -- Do not sort the shopping basket table and just use the current order
5038 -- the lines are in.
5039 IF (l_debug = 1) THEN
5040 print_debug('3.6 - Invalid output from Sort_Supply_Lines API');
5041 print_debug('3.6 - Do not sort the supply lines in the shopping basket');
5042 END IF;
5043 ELSE
5044 -- Sort and rebuild the shopping basket table
5045 l_index := l_sorted_order_tb.FIRST;
5046 -- Initialize the indices used table and the temp shopping basket table
5047 l_indices_used_tb.DELETE;
5048 l_shopping_basket_temp_tb.DELETE;
5049 LOOP
5050 -- Make sure the current entry has not already been used.
5051 -- Also make sure the index refered to in l_sorted_order_tb is a valid one
5052 -- in the shopping basket table.
5053 IF (l_indices_used_tb.EXISTS(l_sorted_order_tb(l_index)) OR
5054 NOT l_shopping_basket_tb.EXISTS(l_sorted_order_tb(l_index))) THEN
5055 IF (l_debug = 1) THEN
5056 print_debug('3.6 - Sorted order table is invalid so do not sort the supply lines');
5057 END IF;
5058 -- Clear the temp shopping basket table
5059 l_shopping_basket_temp_tb.DELETE;
5060 -- Exit out of the loop. No sorting will be done.
5061 GOTO invalid_sorting;
5062 END IF;
5063
5064 -- Mark the current pointer index to the shopping basket table as used
5065 l_indices_used_tb(l_sorted_order_tb(l_index)) := TRUE;
5066
5067 -- Add this entry to the temp shopping basket table.
5068 l_shopping_basket_temp_tb(l_shopping_basket_temp_tb.COUNT + 1) :=
5069 l_shopping_basket_tb(l_sorted_order_tb(l_index));
5070
5071 EXIT WHEN l_index = l_sorted_order_tb.LAST;
5072 l_index := l_sorted_order_tb.NEXT(l_index);
5073 END LOOP;
5074
5075 -- Set the shopping basket table to point to the new sorted one
5076 l_shopping_basket_tb := l_shopping_basket_temp_tb;
5077 l_shopping_basket_temp_tb.DELETE;
5078 IF (l_debug = 1) THEN
5079 print_debug('3.6 - Finished sorting and rebuilding the shopping basket table');
5080 END IF;
5081
5082 -- In case of an invalid sorted order table, jump to this label below and
5083 -- do not sort the shopping basket at all.
5084 <<invalid_sorting>>
5085 NULL; -- Need an executable statement for the above label to work
5086 END IF;
5087 l_progress := '460';
5088
5089 END IF; -- End of crossdocking goal = CUSTOM
5090
5091 -- Section 4: Consume the valid supply lines for crossdocking to the demand line
5092 -- 4.1 - Lock the supply line record(s).
5093 -- 4.2 - Call the available to reserve API to see how much quantity from the supply
5094 -- is valid for crossdocking.
5095 -- 4.3 - Crossdock the demand and supply line records.
5096 -- 4.4 - Create a crossdocked reservation tying the demand to the supply line.
5097 -- 4.5 - Bulk update the reservable_quantity for all crossdocked supply lines in the
5098 -- global temp table, wms_xdock_pegging_gtmp.
5099
5100 -- Check if there are valid supply lines found for crossdocking.
5101 -- If none exist, move on to the next WDD record to crossdock.
5102 IF (l_shopping_basket_tb.COUNT = 0) THEN
5103 IF (l_debug = 1) THEN
5104 print_debug('4.1 - No valid supply lines for crossdocking were found');
5105 END IF;
5106 GOTO next_record;
5107 END IF;
5108
5109 -- Initialize the shopping basket supply lines index. This should not be a NULL value.
5110 l_supply_index := NVL(l_shopping_basket_tb.FIRST, 1);
5111
5112 -- Initialize the supply ATR tables used to do a bulk update for the supply lines
5113 -- crossdocked sucessfully for the reservable_quantity column.
5114 l_supply_rowid_tb.DELETE;
5115 l_supply_atr_qty_tb.DELETE;
5116
5117 -- Define a savepoint so if an exception occurs when performing the bulk update
5118 -- of supply lines in wms_xdock_pegging_gtmp after the supply lines shopping basket loop,
5119 -- we want to rollback all crossdock changes done within the loop.
5120 SAVEPOINT Before_Supply_Loop_sp;
5121
5122 -- Loop through the valid supply lines to crossdock the current WDD demand
5123 LOOP
5124 -- Define a savepoint so if an exception occurs while updating database records such as
5125 -- WDD, RSV, or MOL, we need to rollback the changes and goto the next WDD record
5126 -- to crossdock. Put this inside the supply lines loop so if one supply line
5127 -- is crossdocked successfully but another one errors out, we can still crossdock
5128 -- the first one.
5129 SAVEPOINT Crossdock_Supply_sp;
5130
5131 -- Initialize the variables to store the original WDD values in case
5132 -- we need to rollback the changes to local PLSQL data structures
5133 l_split_wdd_index := NULL;
5134 l_split_delivery_index := NULL;
5135 l_xdocked_wdd_index := NULL;
5136 l_orig_wdd_values_rec := NULL;
5137
5138 -- Initialize the supply ATR index variable which is used to update
5139 -- the ATR qty for the supply lines used in this loop when crossdocked.
5140 l_supply_atr_index := NULL;
5141
5142 -- Retrieve needed values from the current supply line
5143 l_supply_type_id := l_shopping_basket_tb(l_supply_index).source_type_id;
5144 l_supply_header_id := l_shopping_basket_tb(l_supply_index).source_header_id;
5145 l_supply_line_id := l_shopping_basket_tb(l_supply_index).source_line_id;
5146 l_supply_line_detail_id := l_shopping_basket_tb(l_supply_index).source_line_detail_id;
5147 IF (l_debug = 1) THEN
5148 print_debug('4.1 - Current supply line to consider for crossdocking');
5149 print_debug('4.1 - Supply Source Type ID: => ' || l_supply_type_id);
5150 print_debug('4.1 - Supply Header ID: ======> ' || l_supply_header_id);
5151 print_debug('4.1 - Supply Line ID: ========> ' || l_supply_line_id);
5152 print_debug('4.1 - Supply Line Detail ID: => ' || l_supply_line_detail_id);
5153 END IF;
5154
5155 -- If the supply type is In Receiving, retrieve the necessary MOL values.
5156 -- They will be used to update/split the MOL supply line used for crossdocking.
5157 IF (l_supply_type_id = 27) THEN
5158 l_mol_header_id := l_supply_header_id;
5159 l_mol_line_id := l_supply_line_id;
5160 l_mol_qty := l_shopping_basket_tb(l_supply_index).quantity;
5161 l_mol_prim_qty := l_shopping_basket_tb(l_supply_index).primary_quantity;
5162 l_mol_qty2 := l_shopping_basket_tb(l_supply_index).secondary_quantity;
5163 l_mol_uom_code2 := l_shopping_basket_tb(l_supply_index).secondary_uom_code;
5164 l_mol_lpn_id := l_shopping_basket_tb(l_supply_index).lpn_id;
5165 ELSE
5166 l_mol_line_id := NULL;
5167 END IF;
5168
5169 -- For non-existing reservations, we do not need to match the UOM code on the supply line
5170 l_supply_uom_code := NULL;
5171
5172 -- In case the supply is of type 'In Receiving' and the org is not PJM enabled OR
5173 -- cross project allocation is allowed, set the supply project and task ID to the
5174 -- dummy values. This is used to see if the set of MOLs for the project/task have been
5175 -- locked already or not. For supply types other than In Receiving, this is not used.
5176 IF (l_project_ref_enabled = 2 OR l_allow_cross_proj_issues = 'Y') THEN
5177 l_supply_project_id := l_dummy_project_id;
5178 l_supply_task_id := l_dummy_task_id;
5179 ELSE
5180 l_supply_project_id := l_shopping_basket_tb(l_supply_index).project_id;
5181 l_supply_task_id := l_shopping_basket_tb(l_supply_index).task_id;
5182 END IF;
5183
5184 -- 4.1 - Lock the supply line record(s).
5185 -- Do this only if the supply line has not already been locked.
5186 -- For non-Receiving supply types, we can just check if the reservable_quantity field is null.
5187 -- For Receiving supply types, since we lock an entire set of MOLs at once, we do not want to
5188 -- do this again if not necessary. For example, say there are two valid MOLs for Item1, call
5189 -- them MOL1 and MOL2. Both records are pulled into the shopping basket table. When we
5190 -- first encounter MOL1, the MOLs associated with Item1 have not been locked yet. The set
5191 -- of MOLs we will lock also includes MOL2. When we next use MOL2 as a supply line for
5192 -- crossdocking, it is unnecessary to lock this record since it has already been done.
5193 -- We might still have to calculate the ATR qty even though the record has been locked.
5194 -- That is why for MOLs, we cannot rely on the reservable_quantity field.
5195 IF ((l_supply_type_id <> 27 AND l_shopping_basket_tb(l_supply_index).reservable_quantity IS NULL)
5196 OR
5197 (l_supply_type_id = 27 AND l_shopping_basket_tb(l_supply_index).reservable_quantity IS NULL
5198 AND NOT (l_locked_mols_tb.EXISTS(l_inventory_item_id) AND
5199 l_locked_mols_tb(l_inventory_item_id).EXISTS(l_supply_project_id) AND
5200 l_locked_mols_tb(l_inventory_item_id)(l_supply_project_id).EXISTS(l_supply_task_id))))
5201 THEN
5202 -- We do not need to use these cursors to retrieve the supply line UOM code, project
5203 -- and task ID since that information is already stored in the shopping basket table.
5204 -- We are doing that here so we can reuse the same locking cursors used for crossdocking
5205 -- existing reservations.
5206 IF (l_supply_type_id = 1) THEN
5207 -- PO
5208 BEGIN
5209 OPEN lock_po_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
5210 FETCH lock_po_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
5211 IF (lock_po_record%NOTFOUND) THEN
5212 -- If a record is not found, do not error out. This error condition should not
5213 -- occur since the supply lines retrieved should already satisfy the project
5214 -- and task restrictions. Skip this supply line and move on to the next one.
5215 IF (l_debug = 1) THEN
5216 print_debug('4.1 - Supply record not found. UOM/project/task values do not match');
5217 END IF;
5218 CLOSE lock_po_record;
5219 -- Rollback any db changes that might have occurred (currently none).
5220 ROLLBACK TO Crossdock_Supply_sp;
5221 GOTO next_supply;
5222 END IF;
5223 CLOSE lock_po_record;
5224 EXCEPTION
5225 WHEN OTHERS THEN
5226 IF (l_debug = 1) THEN
5227 print_debug('4.1 - Could not lock the PO supply line record');
5228 END IF;
5229 -- If we cannot lock the supply line, do not error out. Just go to the
5230 -- next available supply and try to crossdock that.
5231 -- Rollback any db changes that might have occurred (currently none).
5232 ROLLBACK TO Crossdock_Supply_sp;
5233 GOTO next_supply;
5234 END;
5235 ELSIF (l_supply_type_id = 7) THEN
5236 -- Internal Requisition
5237 BEGIN
5238 OPEN lock_intreq_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
5239 -- Multiple records could be returned from this cursor. We only care about existence.
5240 FETCH lock_intreq_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
5241 IF (lock_intreq_record%NOTFOUND) THEN
5242 -- If a record is not found, do not error out. This error condition should not
5243 -- occur since the supply lines retrieved should already satisfy the project
5244 -- and task restrictions. Skip this supply line and move on to the next one.
5245 IF (l_debug = 1) THEN
5246 print_debug('4.1 - Supply record not found. UOM/project/task values do not match');
5247 END IF;
5248 CLOSE lock_intreq_record;
5249 -- Rollback any db changes that might have occurred (currently none).
5250 ROLLBACK TO Crossdock_Supply_sp;
5251 GOTO next_supply;
5252 END IF;
5253 CLOSE lock_intreq_record;
5254 EXCEPTION
5255 WHEN OTHERS THEN
5256 IF (l_debug = 1) THEN
5257 print_debug('4.1 - Could not lock the Internal Req supply line record');
5258 END IF;
5259 -- If we cannot lock the supply line, do not error out. Just go to the
5260 -- next available supply and try to crossdock that.
5261 -- Rollback any db changes that might have occurred (currently none).
5262 ROLLBACK TO Crossdock_Supply_sp;
5263 GOTO next_supply;
5264 END;
5265 ELSIF (l_supply_type_id = 25) THEN
5266 -- ASN
5267 BEGIN
5268 OPEN lock_asn_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
5269 FETCH lock_asn_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
5270 IF (lock_asn_record%NOTFOUND) THEN
5271 -- If a record is not found, do not error out. This error condition should not
5272 -- occur since the supply lines retrieved should already satisfy the project
5273 -- and task restrictions. Skip this supply line and move on to the next one.
5274 IF (l_debug = 1) THEN
5275 print_debug('4.1 - Supply record not found. UOM/project/task values do not match');
5276 END IF;
5277 CLOSE lock_asn_record;
5278 -- Rollback any db changes that might have occurred (currently none).
5279 ROLLBACK TO Crossdock_Supply_sp;
5280 GOTO next_supply;
5281 END IF;
5282 CLOSE lock_asn_record;
5283 EXCEPTION
5284 WHEN OTHERS THEN
5285 IF (l_debug = 1) THEN
5286 print_debug('4.1 - Could not lock the ASN supply line record');
5287 END IF;
5288 -- If we cannot lock the supply line, do not error out. Just go to the
5289 -- next available supply and try to crossdock that.
5290 -- Rollback any db changes that might have occurred (currently none).
5291 ROLLBACK TO Crossdock_Supply_sp;
5292 GOTO next_supply;
5293 END;
5294 ELSIF (l_supply_type_id = 26) THEN
5295 -- In Transit Shipment
5296 BEGIN
5297 OPEN lock_intship_record(l_supply_uom_code, l_demand_project_id, l_demand_task_id);
5298 FETCH lock_intship_record INTO l_supply_uom_code, l_supply_project_id, l_supply_task_id;
5299 IF (lock_intship_record%NOTFOUND) THEN
5300 -- If a record is not found, do not error out. This error condition should not
5301 -- occur since the supply lines retrieved should already satisfy the project
5302 -- and task restrictions. Skip this supply line and move on to the next one.
5303 IF (l_debug = 1) THEN
5304 print_debug('4.1 - Supply record not found. UOM/project/task values do not match');
5305 END IF;
5306 CLOSE lock_intship_record;
5307 -- Rollback any db changes that might have occurred (currently none).
5308 ROLLBACK TO Crossdock_Supply_sp;
5309 GOTO next_supply;
5310 END IF;
5311 CLOSE lock_intship_record;
5312 EXCEPTION
5313 WHEN OTHERS THEN
5314 IF (l_debug = 1) THEN
5315 print_debug('4.1 - Could not lock the In Transit Shipment supply line record');
5316 END IF;
5317 -- If we cannot lock the supply line, do not error out. Just go to the
5318 -- next available supply and try to crossdock that.
5319 -- Rollback any db changes that might have occurred (currently none).
5320 ROLLBACK TO Crossdock_Supply_sp;
5321 GOTO next_supply;
5322 END;
5323 ELSIF (l_supply_type_id = 27) THEN
5324 -- In Receiving
5325 -- We need to lock the set of MOLs that match the given crossdocking criteria for:
5326 -- org, item, UOM, project and task.
5327 -- Initialize the table we are fetching records into. For this case, we do not need
5328 -- to use the values stored there since we are going against the shopping basket
5329 -- supply line records directly.
5330 l_rcv_lines_tb.DELETE;
5331 BEGIN
5332 OPEN lock_receiving_lines(l_supply_uom_code, l_demand_atr_prim_qty,
5333 l_demand_project_id, l_demand_task_id);
5334 FETCH lock_receiving_lines BULK COLLECT INTO l_rcv_lines_tb;
5335 -- If a record is not found, do not error out. This error condition should not
5336 -- occur since the supply lines retrieved should already satisfy the project
5337 -- and task restrictions. Skip this supply line and move on to the next one.
5338 IF (l_rcv_lines_tb.COUNT = 0) THEN
5339 IF (l_debug = 1) THEN
5340 print_debug('4.1 - No valid receiving supply lines found');
5341 END IF;
5342 CLOSE lock_receiving_lines;
5343 -- Rollback any db changes that might have occurred (currently none).
5344 ROLLBACK TO Crossdock_Supply_sp;
5345 GOTO next_supply;
5346 END IF;
5347 CLOSE lock_receiving_lines;
5348 EXCEPTION
5349 WHEN OTHERS THEN
5350 IF (l_debug = 1) THEN
5351 print_debug('4.1 - Could not lock the Receiving supply line records');
5352 END IF;
5353 -- If we cannot lock the supply lines, do not error out. Just go to the
5354 -- next available supply and try to crossdock that.
5355 -- Rollback any db changes that might have occurred (currently none).
5356 ROLLBACK TO Crossdock_Supply_sp;
5357 GOTO next_supply;
5358 END;
5359 -- Clear the table since we do not need to use it
5360 l_rcv_lines_tb.DELETE;
5361
5362 -- Indicate that this set of MOLs for the given item has already been locked.
5363 IF (l_project_ref_enabled = 2 OR l_allow_cross_proj_issues = 'Y') THEN
5364 -- No need to store the project/task info so just use the
5365 -- dummy project/task ID values.
5366 l_locked_mols_tb(l_inventory_item_id)(l_dummy_project_id)(l_dummy_task_id) := TRUE;
5367 ELSE
5368 -- We need to store the specific project/task info.
5369 -- Since we have to match the project/task here, the supply line in the
5370 -- shopping basket should have the same values as the demand.
5371 l_locked_mols_tb(l_inventory_item_id)(NVL(l_demand_project_id, -999))(NVL(l_demand_task_id, -999)) := TRUE;
5372 END IF;
5373 ELSE
5374 -- Invalid supply for crossdocking. Should not reach this condition.
5375 -- Rollback any db changes that might have occurred (currently none).
5376 ROLLBACK TO Crossdock_Supply_sp;
5377 GOTO next_supply;
5378 END IF; -- End locking supply line(s) from different source types
5379 END IF; -- End check if reservable_quantity IS NOT NULL
5380
5381 -- Reset these values to the ones stored in the shopping basket table.
5382 -- The values could differ if the supply line is In Receiving since multiple
5383 -- MOLs are locked/retrieved for the current supply line (MOL) in the shopping basket.
5384 l_supply_uom_code := l_shopping_basket_tb(l_supply_index).uom_code;
5385 l_supply_project_id := l_shopping_basket_tb(l_supply_index).project_id;
5386 l_supply_task_id := l_shopping_basket_tb(l_supply_index).task_id;
5387 IF (l_debug = 1) THEN
5388 print_debug('4.1 - Successfully locked and validated the supply line record(s)');
5389 print_debug('4.1 - Supply UOM Code: ===> ' || l_supply_uom_code);
5390 print_debug('4.1 - Supply Project ID: => ' || l_supply_project_id);
5391 print_debug('4.1 - Supply Task ID: ====> ' || l_supply_task_id);
5392 END IF;
5393 l_progress := '470';
5394
5395 -- 4.2 - Call the available to reserve API to see how much quantity from the supply
5396 -- is valid for crossdocking.
5397 -- Check if this value has already been queried and stored in the global temp table.
5398 -- The shopping basket record for the supply line will have a non null value for the
5399 -- reservable_quantity field. This means the supply line was locked and used for
5400 -- crossdocking previously. In that case, we do not need to call the available to
5401 -- reserve API's again.
5402 IF (l_shopping_basket_tb(l_supply_index).reservable_quantity IS NULL) THEN
5403 IF (l_debug = 1) THEN
5404 print_debug('4.2 - Call the Available_supply_to_reserve API');
5405 END IF;
5406 INV_RESERVATION_AVAIL_PVT.Available_supply_to_reserve
5407 (p_api_version_number => 1.0,
5408 p_init_msg_lst => fnd_api.g_false,
5409 x_return_status => x_return_status,
5410 x_msg_count => x_msg_count,
5411 x_msg_data => x_msg_data,
5412 p_organization_id => l_organization_id,
5413 p_item_id => l_inventory_item_id,
5414 p_supply_source_type_id => l_supply_type_id,
5415 p_supply_source_header_id => l_supply_header_id,
5416 p_supply_source_line_id => l_supply_line_id,
5417 p_supply_source_line_detail => l_supply_line_detail_id,
5418 p_project_id => l_supply_project_id,
5419 p_task_id => l_supply_task_id,
5420 x_qty_available_to_reserve => l_supply_atr_prim_qty,
5421 x_qty_available => l_supply_available_qty);
5422
5423 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5424 IF (l_debug = 1) THEN
5425 print_debug('4.2 - Error returned from available_supply_to_reserve API: '
5426 || x_return_status);
5427 END IF;
5428 -- Rollback any db changes that might have occurred (currently none).
5429 ROLLBACK TO Crossdock_Supply_sp;
5430 GOTO next_supply;
5431 --RAISE fnd_api.g_exc_error;
5432 END IF;
5433
5434 -- If the supply is 'In Receiving', the ATR qty returned is for all of receiving.
5435 -- Since we're working on a specific MOL supply line, we need to use a LEAST
5436 -- to get the min qty value.
5437 IF (l_supply_type_id = 27) THEN
5438
5439 l_supply_atr_prim_qty := LEAST(l_mol_prim_qty, l_supply_atr_prim_qty);
5440
5441 END IF;
5442
5443 -- Convert the ATR primary quantity to the UOM on the supply line
5444 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
5445 l_primary_uom_code, l_supply_uom_code);
5446 IF (l_conversion_rate < 0) THEN
5447 IF (l_debug = 1) THEN
5448 print_debug('4.2 - Error while obtaining Primary UOM conversion rate for supply line');
5449 END IF;
5450 -- Rollback any db changes that might have occurred (currently none).
5451 ROLLBACK TO Crossdock_Supply_sp;
5452 GOTO next_supply;
5453 END IF;
5454 -- Round the converted quantity to the standard precision
5455 l_supply_atr_qty := ROUND(l_conversion_rate * l_supply_atr_prim_qty, l_conversion_precision);
5456
5457 -- Set the reservable quantity field for the current supply line
5458 -- in the shopping basket table.
5459 l_shopping_basket_tb(l_supply_index).reservable_quantity := l_supply_atr_qty;
5460
5461 ELSIF (l_shopping_basket_tb(l_supply_index).reservable_quantity IS NOT NULL) THEN
5462 -- ATR quantity has already been calculated for this supply line
5463 l_supply_atr_qty := l_shopping_basket_tb(l_supply_index).reservable_quantity;
5464 END IF; -- End retrieving the ATR supply quantity
5465 IF (l_debug = 1) THEN
5466 print_debug('4.2 - Supply line ATR qty: ' || l_supply_atr_qty || ' ' ||
5467 l_supply_uom_code);
5468 END IF;
5469 -- If the current supply line has no reservable quantity,
5470 -- skip it and go to the next available supply line.
5471 IF (l_supply_atr_qty <= 0) THEN
5472 IF (l_debug = 1) THEN
5473 print_debug('4.2 - Supply ATR qty <= 0 so skip to next available supply');
5474 END IF;
5475 -- Rollback any db changes that might have occurred (currently none).
5476 ROLLBACK TO Crossdock_Supply_sp;
5477 GOTO next_supply;
5478 END IF;
5479 l_progress := '480';
5480
5481 -- 4.3 - Crossdock the demand and supply line records.
5482 IF (l_debug = 1) THEN
5483 print_debug('4.3 - Crossdock the demand and supply line records');
5484 END IF;
5485
5486 -- Convert the WDD ATR qty to the UOM on the supply line. This value should not be zero if
5487 -- we have reached this point. If this was calculated as zero previously in section 2.6,
5488 -- we would have skipped to the next WDD record to crossdock.
5489 -- Also convert the WDD qty to the UOM on the supply line. Since they use the same
5490 -- conversion rate, we just need to retrieve that value once.
5491 -- This is required so we know if the WDD line needs to be split or not. That would depend
5492 -- on the WDD qty, not the WDD ATR qty.
5493 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
5494 l_demand_uom_code, l_supply_uom_code);
5495 IF (l_conversion_rate < 0) THEN
5496 IF (l_debug = 1) THEN
5497 print_debug('4.3 - Error while obtaining UOM conversion rate for WDD qty');
5498 END IF;
5499 -- Rollback any db changes that might have occurred (currently none).
5500 ROLLBACK TO Crossdock_Supply_sp;
5501 GOTO next_supply;
5502 END IF;
5503 -- Round the converted quantity to the standard precision
5504 l_wdd_atr_txn_qty := ROUND(l_conversion_rate * l_demand_atr_qty, l_conversion_precision);
5505 l_wdd_txn_qty := ROUND(l_conversion_rate * l_demand_qty, l_conversion_precision);
5506 IF (l_debug = 1) THEN
5507 print_debug('4.3 - WDD ATR txn qty: => ' || l_wdd_atr_txn_qty || ' ' || l_supply_uom_code);
5508 print_debug('4.3 - WDD txn qty: =====> ' || l_wdd_txn_qty || ' ' || l_supply_uom_code);
5509 END IF;
5510 l_progress := '490';
5511
5512 -- Calculate the Available to Detail quantity.
5513 -- {{
5514 -- Test that the available to detail quantity is calculated properly,
5515 -- i.e. is lower than WDD ATR qty and supply line qty, and is an integer value if
5516 -- UOM integrity = 'Y'. }}
5517 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1) THEN
5518 -- UOM Integrity is 'Yes'
5519 l_atd_qty := LEAST(FLOOR(l_wdd_atr_txn_qty), FLOOR(l_supply_atr_qty));
5520 ELSE
5521 -- UOM Integrity is 'No'
5522 l_atd_qty := LEAST(l_wdd_atr_txn_qty, l_supply_atr_qty);
5523 END IF;
5524 IF (l_debug = 1) THEN
5525 print_debug('4.3 - Available to detail qty: ' || l_atd_qty || ' ' ||
5526 l_supply_uom_code);
5527 END IF;
5528 -- If the ATD qty is 0, then goto the next supply line to crossdock.
5529 -- This is possible if the UOM integrity flag is 'Y' and the resultant quantities
5530 -- were floored to 0.
5531 -- {{
5532 -- Test for ATD qty = 0. This can come about if UOM integrity is Yes and the
5533 -- demand or supply line with available to reserve qty gets floored to 0. }}
5534 IF (l_atd_qty = 0) THEN
5535 IF (l_debug = 1) THEN
5536 print_debug('4.3 - ATD qty = 0 so skip to the next available supply');
5537 END IF;
5538 -- Rollback any db changes that might have occurred (currently none).
5539 ROLLBACK TO Crossdock_Supply_sp;
5540 GOTO next_supply;
5541 END IF;
5542 l_progress := '500';
5543
5544 -- Update the supply line record in the global temp table with the reservable_quantity
5545 -- available after using up ATD qty from it for crossdocking.
5546 -- Do not do this if the supply is of type In Receiving or Internal Requisition.
5547 -- The reason is there can be multiple supply lines of these types in the shopping
5548 -- basket table. However, when we create reservations, they will not be at that
5549 -- line level detail. e.g. Receiving supply reservations will only be at the org/item
5550 -- level while Internal Reqs will be at the Req header/line level (and not the shipment
5551 -- line level). Availability to reserve needs to take the whole set of lines into account
5552 -- so it should be recalculated each time.
5553 IF (l_supply_type_id NOT IN (7, 27)) THEN
5554 IF (l_debug = 1) THEN
5555 print_debug('4.3 - Update the ATR qty for the crossdocked supply line');
5556 END IF;
5557 -- Instead of updating the supply line record here within the supply lines loop,
5558 -- just store the values for the record that needs to be updated. We will do a
5559 -- bulk update outside the loop. In case of exception for the current supply line
5560 -- used for crossdocking, we should remove that record from these tables so the
5561 -- global temp table won't be updated incorrectly. This needs to be only done
5562 -- when we are still staying within the supply lines loop. For exceptions where
5563 -- we go to the next_record, we do not need to remove the current supply line record.
5564 -- The reason is because the bulk update logic after the supply lines loop is skipped.
5565 l_supply_atr_index := l_supply_rowid_tb.COUNT + 1;
5566 l_supply_rowid_tb(l_supply_atr_index) := l_shopping_basket_tb(l_supply_index).ROWID;
5567
5568 if l_simulation_mode = 'N' THEN
5569 l_supply_atr_qty_tb(l_supply_atr_index) := l_supply_atr_qty - l_atd_qty;
5570 ELSE
5571
5572
5573
5574 if l_split_flag = 'Y' then
5575
5576 l_supply_atr_qty_tb(l_supply_atr_index) := l_supply_atr_qty-l_atd_wdd_qty;
5577 -- print_debug('Ajith l_atd_wdd_qty '||to_number(l_supply_atr_qty-l_atd_wdd_qty));
5578
5579
5580 ELSE
5581
5582 l_supply_atr_qty_tb(l_supply_atr_index) := l_supply_atr_qty-l_wdd_txn_qty;
5583
5584 -- print_debug('Ajith l_wdd_txn_qty '||to_number(l_supply_atr_qty-l_wdd_txn_qty));
5585 end if;
5586 END IF;
5587
5588 -- Commented the below out since we will do a bulk update instead outside
5589 -- the supply lines loop
5590 /*BEGIN
5591 UPDATE wms_xdock_pegging_gtmp
5592 SET reservable_quantity = l_supply_atr_qty - l_atd_qty
5593 WHERE ROWID = l_shopping_basket_tb(l_supply_index).ROWID;
5594 EXCEPTION
5595 WHEN OTHERS THEN
5596 IF (l_debug = 1) THEN
5597 print_debug('4.3 - Could not update the ATR quantity for the supply line');
5598 END IF;
5599 -- If we cannot udpate the qty on the supply line, do not error out.
5600 -- Just go to the next available supply and try to crossdock that.
5601 -- Null out the reservable qty value set in the shopping basket table.
5602 l_shopping_basket_tb(l_supply_index).reservable_quantity := NULL;
5603 -- Rollback any db changes that might have occurred
5604 ROLLBACK TO Crossdock_Supply_sp;
5605 GOTO next_supply;
5606 END;*/
5607 END IF;
5608 l_progress := '510';
5609
5610 -- Convert l_atd_qty to the primary UOM
5611 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
5612 l_supply_uom_code, l_primary_uom_code);
5613 IF (l_conversion_rate < 0) THEN
5614 IF (l_debug = 1) THEN
5615 print_debug('4.3 - Error while obtaining primary UOM conversion rate for ATD qty');
5616 END IF;
5617 -- Rollback any db changes that might have occurred (currently none).
5618 ROLLBACK TO Crossdock_Supply_sp;
5619 -- Remove the supply line from these tables so the ATR qty is not updated
5620 IF (l_supply_atr_index IS NOT NULL) THEN
5621 l_supply_rowid_tb.DELETE(l_supply_atr_index);
5622 l_supply_atr_qty_tb.DELETE(l_supply_atr_index);
5623 END IF;
5624 GOTO next_supply;
5625 END IF;
5626 -- Convert l_atd_qty to the primary UOM
5627 -- Bug 5608611: Use quantity from demand document where possible
5628 IF (l_atd_qty = l_wdd_atr_txn_qty AND l_demand_uom_code = l_primary_uom_code) THEN
5629 l_atd_prim_qty := l_demand_atr_qty;
5630 ELSE
5631 -- Round the converted quantity to the standard precision
5632 l_atd_prim_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
5633 END IF;
5634 IF (l_debug = 1) THEN
5635 print_debug('4.3 - ATD qty in primary UOM: => ' || l_atd_prim_qty || ' ' ||
5636 l_primary_uom_code);
5637 END IF;
5638 l_progress := '520';
5639
5640 -- Store the original WDD values in case of rollback where we need
5641 -- to clean up the local PLSQL data structures
5642 l_orig_wdd_values_rec.requested_quantity :=
5643 p_wsh_release_table(l_wdd_index).requested_quantity;
5644 l_orig_wdd_values_rec.requested_quantity2 :=
5645 p_wsh_release_table(l_wdd_index).requested_quantity2;
5646 l_orig_wdd_values_rec.released_status :=
5647 p_wsh_release_table(l_wdd_index).released_status;
5648 l_orig_wdd_values_rec.move_order_line_id :=
5649 p_wsh_release_table(l_wdd_index).move_order_line_id;
5650
5651 -- Crossdock the WDD record, splitting it if necessary.
5652 IF (l_debug = 1) THEN
5653 print_debug('4.3 - Call the Crossdock_WDD API to crossdock/split the WDD');
5654 END IF;
5655 Crossdock_WDD
5656 (p_log_prefix => '4.3 - ',
5657 p_crossdock_type => G_CRT_TYPE_PLAN,
5658 p_batch_id => p_batch_id,
5659 p_wsh_release_table => p_wsh_release_table,
5660 p_trolin_delivery_ids => p_trolin_delivery_ids,
5661 p_del_detail_id => p_del_detail_id,
5662 l_wdd_index => l_wdd_index,
5663 l_debug => l_debug,
5664 l_inventory_item_id => l_inventory_item_id,
5665 l_wdd_txn_qty => l_wdd_txn_qty,
5666 l_atd_qty => l_atd_qty,
5667 l_atd_wdd_qty => l_atd_wdd_qty,
5668 l_atd_wdd_qty2 => l_atd_wdd_qty2,
5669 l_supply_uom_code => l_supply_uom_code,
5670 l_demand_uom_code => l_demand_uom_code,
5671 l_demand_uom_code2 => l_demand_uom_code2,
5672 l_conversion_rate => l_conversion_rate,
5673 l_conversion_precision => l_conversion_precision,
5674 l_demand_line_detail_id => l_demand_line_detail_id,
5675 l_index => l_index,
5676 l_detail_id_tab => l_detail_id_tab,
5677 l_action_prms => l_action_prms,
5678 l_action_out_rec => l_action_out_rec,
5679 l_split_wdd_id => l_split_wdd_id,
5680 l_detail_info_tab => l_detail_info_tab,
5681 l_in_rec => l_in_rec,
5682 l_out_rec => l_out_rec,
5683 l_mol_line_id => l_mol_line_id,
5684 l_split_wdd_index => l_split_wdd_index,
5685 l_split_delivery_index => l_split_delivery_index,
5686 l_split_wdd_rel_rec => l_split_wdd_rel_rec,
5687 l_allocation_method => l_allocation_method,
5688 l_demand_qty => l_demand_qty,
5689 l_demand_qty2 => l_demand_qty2,
5690 l_demand_atr_qty => l_demand_atr_qty,
5691 l_xdocked_wdd_index => l_xdocked_wdd_index,
5692 l_supply_type_id => l_supply_type_id,
5693 x_return_status => x_return_status,
5694 x_msg_count => x_msg_count,
5695 x_msg_data => x_msg_data,
5696 x_error_code => l_error_code
5697 );
5698
5699 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5700 IF (l_debug = 1) THEN
5701 print_debug('4.3 - Error returned from Crossdock_WDD API: '
5702 || x_return_status);
5703 END IF;
5704 --RAISE fnd_api.g_exc_error;
5705 -- If an exception occurs while modifying a database record, rollback the changes
5706 -- and just go to the next WDD record or supply to crossdock.
5707 ROLLBACK TO Crossdock_Supply_sp;
5708 -- We need to also rollback changes done to local PLSQL data structures
5709 IF (l_split_wdd_index IS NOT NULL) THEN
5710 p_wsh_release_table.DELETE(l_split_wdd_index);
5711 END IF;
5712 IF (l_split_delivery_index IS NOT NULL) THEN
5713 p_del_detail_id.DELETE(l_split_delivery_index);
5714 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
5715 END IF;
5716 IF (l_xdocked_wdd_index IS NOT NULL) THEN
5717 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
5718 END IF;
5719 p_wsh_release_table(l_wdd_index).requested_quantity :=
5720 l_orig_wdd_values_rec.requested_quantity;
5721 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
5722 l_orig_wdd_values_rec.requested_quantity2;
5723 p_wsh_release_table(l_wdd_index).released_status :=
5724 l_orig_wdd_values_rec.released_status;
5725 p_wsh_release_table(l_wdd_index).move_order_line_id :=
5726 l_orig_wdd_values_rec.move_order_line_id;
5727
5728 -- Skip to the next WDD record or supply to crossdock
5729 IF (l_error_code = 'UOM') THEN
5730 GOTO next_supply;
5731 ELSE -- l_error_code = 'DB'
5732 GOTO next_record;
5733 END IF;
5734 ELSE
5735 if p_simulation_mode = 'Y' THEN
5736
5737 x_wp_crossdock_tbl(l_wdd_index).delivery_detail_id := p_wsh_release_table(l_wdd_index).delivery_detail_id;
5738
5739 if l_split_flag = 'Y' then
5740
5741 x_wp_crossdock_tbl(l_wdd_index).crossdock_qty := l_atd_wdd_qty;
5742
5743 print_debug('In Case of Splitting the crossdocked qty is '||x_wp_crossdock_tbl(l_wdd_index).crossdock_qty);
5744
5745 ELSE
5746
5747 x_wp_crossdock_tbl(l_wdd_index).crossdock_qty := l_wdd_txn_qty;
5748
5749 print_debug('Crossdock Quantity without SPlit '||x_wp_crossdock_tbl(l_wdd_index).crossdock_qty);
5750
5751 end if;
5752 END IF;
5753
5754 IF (l_debug = 1) THEN
5755 print_debug('4.3 - Successfully crossdocked/split the WDD record');
5756 END IF;
5757 END IF;
5758 l_progress := '530';
5759
5760 if p_simulation_mode = 'Y' then
5761
5762 null;
5763
5764 else
5765 -- Crossdock and split the MOL supply line if necessary
5766 IF (l_mol_line_id IS NOT NULL) THEN
5767 IF (l_debug = 1) THEN
5768 print_debug('4.3 - Call the Crossdock_MOL API to crossdock/split the MOL: '
5769 || l_mol_line_id);
5770 END IF;
5771 Crossdock_MOL
5772 (p_log_prefix => '4.3 - ',
5773 p_crossdock_type => G_CRT_TYPE_PLAN,
5774 l_debug => l_debug,
5775 l_inventory_item_id => l_inventory_item_id,
5776 l_mol_qty => l_mol_qty,
5777 l_mol_qty2 => l_mol_qty2,
5778 l_atd_qty => l_atd_qty,
5779 l_atd_mol_qty2 => l_atd_mol_qty2,
5780 l_supply_uom_code => l_supply_uom_code,
5781 l_mol_uom_code2 => l_mol_uom_code2,
5782 l_conversion_rate => l_conversion_rate,
5783 l_conversion_precision => l_conversion_precision,
5784 l_mol_prim_qty => l_mol_prim_qty,
5785 l_atd_prim_qty => l_atd_prim_qty,
5786 l_split_wdd_id => l_split_wdd_id,
5787 l_mol_header_id => l_mol_header_id,
5788 l_mol_line_id => l_mol_line_id,
5789 l_supply_atr_qty => l_supply_atr_qty,
5790 l_demand_type_id => l_demand_type_id,
5791 l_wip_entity_id => l_wip_entity_id,
5792 l_operation_seq_num => l_operation_seq_num,
5793 l_repetitive_schedule_id => l_repetitive_schedule_id,
5794 l_wip_supply_type => l_wip_supply_type,
5795 l_xdocked_wdd_index => l_xdocked_wdd_index,
5796 l_detail_info_tab => l_detail_info_tab,
5797 l_wdd_index => l_wdd_index,
5798 l_split_wdd_index => l_split_wdd_index,
5799 p_wsh_release_table => p_wsh_release_table,
5800 l_supply_type_id => l_supply_type_id,
5801 x_return_status => x_return_status,
5802 x_msg_count => x_msg_count,
5803 x_msg_data => x_msg_data,
5804 x_error_code => l_error_code,
5805 x_new_mol_id => l_new_mol_id --9695544
5806 );
5807
5808 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5809 IF (l_debug = 1) THEN
5810 print_debug('4.3 - Error returned from Crossdock_MOL API: '
5811 || x_return_status);
5812 END IF;
5813 --RAISE fnd_api.g_exc_error;
5814 -- If an exception occurs while modifying a database record, rollback the changes
5815 -- and just go to the next WDD record or supply to crossdock.
5816 ROLLBACK TO Crossdock_Supply_sp;
5817 -- We need to also rollback changes done to local PLSQL data structures
5818 IF (l_split_wdd_index IS NOT NULL) THEN
5819 p_wsh_release_table.DELETE(l_split_wdd_index);
5820 END IF;
5821 IF (l_split_delivery_index IS NOT NULL) THEN
5822 p_del_detail_id.DELETE(l_split_delivery_index);
5823 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
5824 END IF;
5825 IF (l_xdocked_wdd_index IS NOT NULL) THEN
5826 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
5827 END IF;
5828 p_wsh_release_table(l_wdd_index).requested_quantity :=
5829 l_orig_wdd_values_rec.requested_quantity;
5830 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
5831 l_orig_wdd_values_rec.requested_quantity2;
5832 p_wsh_release_table(l_wdd_index).released_status :=
5833 l_orig_wdd_values_rec.released_status;
5834 p_wsh_release_table(l_wdd_index).move_order_line_id :=
5835 l_orig_wdd_values_rec.move_order_line_id;
5836
5837 -- Skip to the next WDD record or supply to crossdock
5838 IF (l_error_code = 'UOM') THEN
5839 GOTO next_supply;
5840 ELSE -- l_error_code = 'DB'
5841 GOTO next_record;
5842 END IF;
5843 ELSE
5844 IF (l_debug = 1) THEN
5845 print_debug('4.3 - Successfully crossdocked/split the MOL record');
5846 END IF;
5847 END IF;
5848
5849 -- Store this LPN in the crossdocked LPNs table so we can call the pre_generate
5850 -- API later on for the entire set of LPN's instead of once for each MOL that
5851 -- is crossdocked.
5852 IF (NOT l_crossdocked_lpns_tb.EXISTS(l_mol_lpn_id)) THEN
5853 l_crossdocked_lpns_tb(l_mol_lpn_id) := TRUE;
5854 IF (l_debug = 1) THEN
5855 print_debug('4.3 - Successfully stored the crossdocked LPN: ' || l_mol_lpn_id);
5856 END IF;
5857 END IF;
5858 l_progress := '540';
5859
5860 end if; --Simulation Mode
5861 END IF; -- End of l_mol_line_id IS NOT NULL for receiving supply type
5862
5863
5864 -- 4.4 - Create a crossdocked reservation tying the demand to the supply line.
5865 -- Calculate the supply expected time
5866 IF (l_debug = 1) THEN
5867 print_debug('4.4 - Create a crossdock reservation peg to tie the demand to the supply');
5868 END IF;
5869 IF (l_shopping_basket_tb(l_supply_index).dock_start_time IS NOT NULL) THEN
5870 -- Get the supply dock schedule method to decide which
5871 -- dock appointment time to use as the supply expected time
5872 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).supply_schedule_method IS NULL OR
5873 g_crossdock_criteria_tb(l_crossdock_criteria_id).supply_schedule_method = G_APPT_MEAN_TIME) THEN
5874 l_supply_expected_time := l_shopping_basket_tb(l_supply_index).dock_mean_time;
5875 ELSIF (g_crossdock_criteria_tb(l_crossdock_criteria_id).supply_schedule_method = G_APPT_START_TIME) THEN
5876 l_supply_expected_time := l_shopping_basket_tb(l_supply_index).dock_start_time;
5877 ELSIF (g_crossdock_criteria_tb(l_crossdock_criteria_id).supply_schedule_method = G_APPT_END_TIME) THEN
5878 l_supply_expected_time := l_shopping_basket_tb(l_supply_index).dock_end_time;
5879 END IF;
5880 ELSE
5881 l_supply_expected_time := l_shopping_basket_tb(l_supply_index).expected_time;
5882 END IF;
5883 IF (l_debug = 1) THEN
5884 print_debug('4.4 - Supply line expected time: ' ||
5885 TO_CHAR(l_supply_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
5886 END IF;
5887
5888 if p_simulation_mode = 'Y' then
5889
5890 null;
5891
5892 ELSE
5893 -- Call the Create_RSV API to create a crossdock reservation
5894 IF (l_debug = 1) THEN
5895 print_debug('4.4 - Call the Create_RSV API to create a crossdock reservation');
5896 END IF;
5897 Create_RSV
5898 (p_log_prefix => '4.4 - ',
5899 p_crossdock_type => G_CRT_TYPE_PLAN,
5900 l_debug => l_debug,
5901 l_organization_id => l_organization_id,
5902 l_inventory_item_id => l_inventory_item_id,
5903 l_demand_type_id => l_demand_type_id,
5904 l_demand_so_header_id => l_demand_so_header_id,
5905 l_demand_line_id => l_demand_line_id,
5906 l_split_wdd_id => l_split_wdd_id,
5907 l_primary_uom_code => l_primary_uom_code,
5908 l_demand_uom_code2 => l_demand_uom_code2,
5909 l_supply_uom_code => l_supply_uom_code,
5910 l_atd_qty => l_atd_qty,
5911 l_atd_prim_qty => l_atd_prim_qty,
5912 l_atd_wdd_qty2 => l_atd_wdd_qty2,
5913 l_supply_type_id => l_supply_type_id,
5914 l_supply_header_id => l_supply_header_id,
5915 l_supply_line_id => l_supply_line_id,
5916 l_supply_line_detail_id => l_supply_line_detail_id,
5917 l_crossdock_criteria_id => l_crossdock_criteria_id,
5918 l_supply_expected_time => l_supply_expected_time,
5919 l_demand_expected_time => l_demand_expected_time,
5920 l_demand_project_id => l_demand_project_id,
5921 l_demand_task_id => l_demand_task_id,
5922 l_original_rsv_rec => l_original_rsv_rec,
5923 l_original_serial_number => l_original_serial_number,
5924 l_to_serial_number => l_to_serial_number,
5925 l_quantity_reserved => l_quantity_reserved,
5926 l_quantity_reserved2 => l_quantity_reserved2,
5927 l_rsv_id => l_rsv_id,
5928 x_return_status => x_return_status,
5929 x_msg_count => x_msg_count,
5930 x_msg_data => x_msg_data
5931 );
5932
5933 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5934 IF (l_debug = 1) THEN
5935 print_debug('4.4 - Error returned from create_reservation API: '
5936 || x_return_status);
5937 END IF;
5938 --RAISE fnd_api.g_exc_error;
5939 -- If an exception occurs while modifying a database record, rollback the changes
5940 -- and just go to the next WDD record to crossdock.
5941 ROLLBACK TO Crossdock_Supply_sp;
5942 -- We need to also rollback changes done to local PLSQL data structures
5943 IF (l_split_wdd_index IS NOT NULL) THEN
5944 p_wsh_release_table.DELETE(l_split_wdd_index);
5945 END IF;
5946 IF (l_split_delivery_index IS NOT NULL) THEN
5947 p_del_detail_id.DELETE(l_split_delivery_index);
5948 p_trolin_delivery_ids.DELETE(l_split_delivery_index);
5949 END IF;
5950 IF (l_xdocked_wdd_index IS NOT NULL) THEN
5951 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
5952 END IF;
5953 p_wsh_release_table(l_wdd_index).requested_quantity :=
5954 l_orig_wdd_values_rec.requested_quantity;
5955 p_wsh_release_table(l_wdd_index).requested_quantity2 :=
5956 l_orig_wdd_values_rec.requested_quantity2;
5957 p_wsh_release_table(l_wdd_index).released_status :=
5958 l_orig_wdd_values_rec.released_status;
5959 p_wsh_release_table(l_wdd_index).move_order_line_id :=
5960 l_orig_wdd_values_rec.move_order_line_id;
5961
5962 -- Skip to the next WDD record to crossdock
5963 GOTO next_record;
5964 ELSE
5965 IF (l_debug = 1) THEN
5966 print_debug('4.4 - Successfully created a crossdock RSV record');
5967 END IF;
5968 END IF;
5969 l_progress := '550';
5970
5971 end if; -- Simulation Mode
5972
5973 -- Exit out of valid supply lines loop if the WDD line has been fully crossdocked.
5974 -- There is no need to consider anymore supply lines for crossdocking.
5975 IF (p_wsh_release_table(l_wdd_index).released_status = 'S') THEN
5976 EXIT;
5977 END IF;
5978
5979 <<next_supply>>
5980 -- Exit when all supply lines have been considered
5981 EXIT WHEN l_supply_index = l_shopping_basket_tb.LAST;
5982 l_supply_index := l_shopping_basket_tb.NEXT(l_supply_index);
5983 END LOOP; -- End looping through supply lines in shopping basket table
5984 l_progress := '560';
5985
5986 -- 4.5 - Bulk update the reservable_quantity for all crossdocked supply lines in
5987 -- global temp table, wms_xdock_pegging_gtmp.
5988 -- {{
5989 -- Test that the supply lines used in wms_xdock_pegging_gtmp have the reservable
5990 -- quantities updated properly. In this way, later demand lines to be crossdocked
5991 -- can just refer to this quantity instead of calling the availability APIs again. }}
5992 IF (l_supply_rowid_tb.COUNT > 0) THEN
5993 IF (l_debug = 1) THEN
5994 print_debug('4.5 - For all crossdocked supply lines, update the ATR qty in the temp table');
5995 END IF;
5996
5997 BEGIN
5998 FORALL i IN 1 .. l_supply_rowid_tb.COUNT
5999 UPDATE wms_xdock_pegging_gtmp
6000 SET reservable_quantity = l_supply_atr_qty_tb(i)
6001 WHERE ROWID = l_supply_rowid_tb(i);
6002 EXCEPTION
6003 WHEN OTHERS THEN
6004 IF (l_debug = 1) THEN
6005 print_debug('4.5 - Could not update the ATR qty for the crossdocked supply lines!');
6006 END IF;
6007 -- If an exception occurs while performing this bulk update, raise an exception.
6008 -- This error should not occur but if it does, we should stop the crossdock pegging
6009 -- process.
6010 RAISE fnd_api.g_exc_error;
6011 END;
6012 IF (l_debug = 1) THEN
6013 print_debug('4.5 - Successfully updated the ATR qty for ' || l_supply_rowid_tb.COUNT
6014 || ' (non RCV or Int Req) supply lines ');
6015 END IF;
6016 END IF;
6017 l_progress := '570';
6018
6019
6020 <<next_record>>
6021 EXIT WHEN l_wdd_index = p_wsh_release_table.LAST;
6022 l_wdd_index := p_wsh_release_table.NEXT(l_wdd_index);
6023 END LOOP; -- End looping through records in p_wsh_release_table
6024 l_progress := '580';
6025
6026 -- Section 5: Post crossdocking logic
6027 -- 5.1 - For all crossdocked WDD lines, call the shipping API to update the
6028 -- released_status and move_order_line_id columns.
6029 -- 5.2 - For all of the MOL's and the corresponding LPN's that were crossdocked,
6030 -- call the pre_generate API to create the crossdock tasks.
6031 -- 5.3 - If allocation method is 'C', Crossdock Only or 'X', Prioritize Crossdock,
6032 -- insert all crossdocked WDD lines into the delivery IN OUT tables:
6033 -- p_trolin_delivery_ids and p_del_detail_id.
6034 -- 5.4 - If allocation method is 'N', Prioritize Inventory, backorder all of the
6035 -- WDD lines that could not be allocated. Remove those entries from the
6036 -- delivery IN OUT tables: p_trolin_delivery_ids and p_del_detail_id.
6037 -- 5.5 - Bug 5194761: clear the temp table wms_xdock_pegging_gtmp
6038
6039 -- 5.1 - For all crossdocked WDD lines, call the shipping API to update the
6040 -- released_status and move_order_line_id columns.
6041 -- {{
6042 -- Make sure the shipping API to update crossdocked WDD lines is only called if necessary
6043 -- and properly updates the WDD records. }}
6044
6045 if p_simulation_mode = 'Y' THEN
6046
6047 --Do Bulk Update into the global temp table
6048 print_debug('Updating the wms_wp_rules_simulation table ');
6049
6050 -- ssk autobuild
6051 /* forall m3 in indices of x_wp_crossdock_tbl
6052 update wms_wp_rules_simulation
6053 set crossdocked_quantity = x_wp_crossdock_tbl(m3).crossdock_qty
6054 where delivery_detail_id=x_wp_crossdock_tbl(m3).delivery_detail_id
6055 and wave_header_id = l_wave_header_id; */
6056 IF x_wp_crossdock_tbl.Count > 0 THEN
6057 FOR m3 IN x_wp_crossdock_tbl.first .. x_wp_crossdock_tbl.last LOOP
6058 update wms_wp_rules_simulation
6059 set crossdocked_quantity = x_wp_crossdock_tbl(m3).crossdock_qty
6060 where delivery_detail_id=x_wp_crossdock_tbl(m3).delivery_detail_id
6061 and wave_header_id = l_wave_header_id;
6062 END LOOP;
6063 END IF;
6064 -- ssk autobuild
6065
6066
6067 ELSE
6068 IF (l_detail_info_tab.COUNT > 0) THEN
6069 IF (l_debug = 1) THEN
6070 print_debug('5.1 - Call the Create_Update_Delivery_Detail API for ' ||
6071 l_detail_info_tab.COUNT || ' crossdocked WDD records');
6072 END IF;
6073
6074 l_in_rec.caller := 'WMS_XDOCK_PEGGING_PUB';
6075 l_in_rec.action_code := 'UPDATE';
6076
6077 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
6078 (p_api_version_number => 1.0,
6079 p_init_msg_list => fnd_api.g_false,
6080 p_commit => fnd_api.g_false,
6081 x_return_status => x_return_status,
6082 x_msg_count => x_msg_count,
6083 x_msg_data => x_msg_data,
6084 p_detail_info_tab => l_detail_info_tab,
6085 p_in_rec => l_in_rec,
6086 x_out_rec => l_out_rec
6087 );
6088
6089 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6090 IF (l_debug = 1) THEN
6091 print_debug('5.1 - Error returned from Create_Update_Delivery_Detail API: '
6092 || x_return_status);
6093 END IF;
6094 RAISE FND_API.G_EXC_ERROR;
6095 ELSE
6096 IF (l_debug = 1) THEN
6097 print_debug('5.1 - Successfully updated the crossdocked WDD records');
6098 END IF;
6099 END IF;
6100 END IF;
6101
6102 -- 5.2 - For all of the MOL's and the corresponding LPN's that were crossdocked,
6103 -- call the pre_generate API to create the crossdock tasks.
6104 -- {{
6105 -- Test calling the pre_generate API for crossdocked MOL supply lines used.
6106 -- Make sure the staging lane is stamped properly onto the MOL, operation plans and
6107 -- tasks are generated properly. }}
6108 l_lpn_index := l_crossdocked_lpns_tb.FIRST;
6109
6110 IF (l_crossdocked_lpns_tb.COUNT > 0) THEN
6111 LOOP
6112 -- Call the pre_generate API for the current crossdocked LPN
6113 IF (l_debug = 1) THEN
6114 print_debug('5.2 - Call the pre_generate API for LPN: ' || l_lpn_index);
6115 END IF;
6116 wms_putaway_suggestions.pre_generate
6117 (x_return_status => x_return_status,
6118 x_msg_count => x_msg_count,
6119 x_msg_data => x_msg_data,
6120 x_partial_success => l_partial_success,
6121 x_lpn_line_error_tbl => l_lpn_line_error_tbl,
6122 p_from_conc_pgm => 'N',
6123 p_commit => 'N',
6124 p_organization_id => l_organization_id,
6125 p_lpn_id => l_lpn_index);
6126
6127 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6128 IF (l_debug = 1) THEN
6129 print_debug('5.2 - Error returned from pre_generate API: ' || l_lpn_index
6130 || ': ' || x_return_status);
6131 END IF;
6132 --RAISE fnd_api.g_exc_error;
6133 -- No need to throw an exception if the pre_generate API errors out.
6134 END IF;
6135
6136 EXIT WHEN l_lpn_index = l_crossdocked_lpns_tb.LAST;
6137 l_lpn_index := l_crossdocked_lpns_tb.NEXT(l_lpn_index);
6138 END LOOP; -- End looping through crossdocked LPN's to call the pre_generate API
6139 IF (l_debug = 1) THEN
6140 print_debug('5.2 - Finished calling pre_generate API for all crossdocked LPNs: ' ||
6141 l_crossdocked_lpns_tb.COUNT);
6142 END IF;
6143 l_progress := '590';
6144 END IF;
6145
6146 -- 5.3 - If allocation method is 'C', Crossdock Only or 'X', Prioritize Crossdock,
6147 -- insert all crossdocked WDD lines into the delivery IN OUT tables:
6148 -- p_trolin_delivery_ids and p_del_detail_id.
6149 -- {{
6150 -- Test for allocation method of Crossdock only or Prioritize Crossdock that crossdocked
6151 -- WDD lines are inserted into the delivery tables so shipping can pick them up and autocreate
6152 -- deliveries for them (if this option is set on the pick release form). }}
6153 IF (l_allocation_method = G_CROSSDOCK_ONLY OR
6154 l_allocation_method = G_PRIORITIZE_CROSSDOCK) THEN
6155 -- Initialize the necessary variables
6156 l_unable_to_crossdock := FALSE;
6157 l_wdd_index := p_wsh_release_table.FIRST;
6158 LOOP
6159 IF (p_wsh_release_table.COUNT = 0) THEN
6160 EXIT;
6161 END IF;
6162
6163 -- Insert the crossdocked WDD lines into the delivery tables
6164 IF (p_wsh_release_table(l_wdd_index).released_status = 'S') THEN
6165 l_index := NVL(p_del_detail_id.LAST, 0) + 1;
6166 p_del_detail_id(l_index) := p_wsh_release_table(l_wdd_index).delivery_detail_id;
6167 p_trolin_delivery_ids(l_index) := p_wsh_release_table(l_wdd_index).delivery_id;
6168 ELSIF (p_wsh_release_table(l_wdd_index).released_status IN ('R','B')) THEN
6169 -- For Allocation method of 'Crossdock Only', if any line is not able
6170 -- to be crossdocked, return a warning status to Shipping to alert the user.
6171 IF (l_allocation_method = G_CROSSDOCK_ONLY) THEN
6172 l_unable_to_crossdock := TRUE;
6173 END IF;
6174 END IF;
6175
6176 EXIT WHEN l_wdd_index = p_wsh_release_table.LAST;
6177 l_wdd_index := p_wsh_release_table.NEXT(l_wdd_index);
6178 END LOOP;
6179 IF (l_debug = 1) THEN
6180 print_debug('5.3 - Successfully inserted ' || p_del_detail_id.COUNT ||
6181 ' crossdocked WDD lines into delivery tables');
6182 END IF;
6183 END IF;
6184 l_progress := '600';
6185
6186 -- 5.4 - If allocation method is 'N' (Prioritize Inventory), backorder all of the
6187 -- WDD lines that could not be allocated. Remove those entries from the
6188 -- delivery IN OUT tables: p_trolin_delivery_ids and p_del_detail_id.
6189 -- UPDATE: No need to remove the backordered lines from the delivery tables.
6190 -- This is because shipping does not pass anything in those tables. They expect
6191 -- us to populate those tables with crossdocked WDD lines only.
6192 -- {{
6193 -- Test that for allocation method of Prioritize Inventory, if a line does not get
6194 -- allocated through inventory or crossdock, it should be backordered. }}
6195 IF (l_allocation_method = G_PRIORITIZE_INVENTORY) THEN
6196 -- Initialize the variables
6197 l_wdd_index := p_wsh_release_table.FIRST;
6198 l_index := 1;
6199 l_shipping_attr.DELETE;
6200 l_backordered_wdd_lines := 0;
6201 LOOP
6202 IF (p_wsh_release_table.COUNT = 0) THEN
6203 EXIT;
6204 END IF;
6205
6206 -- Backorder the WDD lines that could not be allocated
6207 -- Bug 5220216
6208 -- For non-reservable item, shipping still calls the pick
6209 -- release API. As a result for prioritize Inventory case
6210 -- this API gets called and if there was a non-reservable
6211 -- item it will get back ordered. Excluding those WDDs.
6212 IF (p_wsh_release_table(l_wdd_index).released_status IN ('R', 'B'))
6213 AND (l_item_params_tb(p_wsh_release_table(l_wdd_index).inventory_item_id).reservable_type <> 2)
6214 THEN
6215 l_shipping_attr(l_index).source_header_id := p_wsh_release_table(l_wdd_index).source_header_id;
6216 l_shipping_attr(l_index).source_line_id := p_wsh_release_table(l_wdd_index).source_line_id;
6217 l_shipping_attr(l_index).ship_from_org_id := p_wsh_release_table(l_wdd_index).organization_id;
6218 l_shipping_attr(l_index).released_status := p_wsh_release_table(l_wdd_index).released_status;
6219 l_shipping_attr(l_index).delivery_detail_id := p_wsh_release_table(l_wdd_index).delivery_detail_id;
6220 l_shipping_attr(l_index).action_flag := 'B';
6221 l_shipping_attr(l_index).cycle_count_quantity := p_wsh_release_table(l_wdd_index).requested_quantity;
6222 l_shipping_attr(l_index).cycle_count_quantity2 := p_wsh_release_table(l_wdd_index).requested_quantity2;
6223 l_shipping_attr(l_index).subinventory := p_wsh_release_table(l_wdd_index).from_sub;
6224 l_shipping_attr(l_index).locator_id := NULL;
6225
6226 -- Increment the index storing the backordered WDD records
6227 l_index := l_index + 1;
6228
6229 -- Store the backordered WDD line in the table so it can
6230 -- be removed from the delivery IN OUT tables.
6231 -- No need to do this anymore since Shipping does not pass in any values in the
6232 -- IN OUT delivery tables. Instead just set the released status of the backordered
6233 -- WDD line in the release table to 'B'. Shipping can make use of this information
6234 -- later on if they do not want to auto-create deliveries for backordered lines.
6235 --l_backordered_wdd_tbl(p_wsh_release_table(l_wdd_index).delivery_detail_id) := TRUE;
6236 l_backordered_wdd_lines := l_backordered_wdd_lines + 1;
6237 p_wsh_release_table(l_wdd_index).released_status := 'B';
6238 END IF;
6239
6240 EXIT WHEN l_wdd_index = p_wsh_release_table.LAST;
6241 l_wdd_index := p_wsh_release_table.NEXT(l_wdd_index);
6242 END LOOP;
6243
6244 -- Call the Shipping API to backorder the WDD lines
6245 IF (l_shipping_attr.COUNT > 0) THEN
6246 IF (l_debug = 1) THEN
6247 print_debug('5.4 - Call the Update_Shipping_Attributes API to backorder ' ||
6248 l_shipping_attr.COUNT || ' WDD records');
6249 END IF;
6250 WSH_INTERFACE.Update_Shipping_Attributes
6251 (p_source_code => 'INV',
6252 p_changed_attributes => l_shipping_attr,
6253 x_return_status => x_return_status
6254 );
6255 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6256 IF (l_debug = 1) THEN
6257 print_debug('5.4 - Error returned from Update_Shipping_Attributes API: '
6258 || x_return_status);
6259 END IF;
6260 RAISE FND_API.G_EXC_ERROR;
6261 END IF;
6262 END IF;
6263
6264 -- Loop through table p_del_detail_id. If that WDD is backordered (value exists in
6265 -- l_backordered_wdd_tbl), then delete that entry from p_del_detail_id and the corresponding
6266 -- one in p_trolin_delivery_ids.
6267 -- UPDATE: No need to do the following logic anymore since Shipping does not populate the
6268 -- delivery tables prior to calling the crossdock/inventory pick release APIs.
6269 -- {{
6270 -- Backordered WDD lines should have their records removed from the shipping delivery
6271 -- tables so the auto-create deliveries process does not pick them up. }}
6272 /*l_index := p_del_detail_id.FIRST;
6273 l_next_index := p_del_detail_id.FIRST;
6274 LOOP
6275 l_index := l_next_index;
6276 l_next_index := p_del_detail_id.NEXT(l_next_index);
6277 -- Exit out of loop when l_index is null, meaning we have
6278 -- reached the last entry in the table.
6279 EXIT WHEN l_index IS NULL;
6280
6281 IF (l_backordered_wdd_tbl.EXISTS(p_del_detail_id(l_index))) THEN
6282 p_del_detail_id.DELETE(l_index);
6283 p_trolin_delivery_ids.DELETE(l_index);
6284 END IF;
6285 END LOOP;*/
6286 IF (l_debug = 1) THEN
6287 print_debug('5.4 - Finished backordering ' || l_backordered_wdd_lines || ' WDD lines');
6288 END IF;
6289 END IF; -- End of: IF (l_allocation_method = G_PRIORITIZE_INVENTORY) THEN
6290 l_progress := '610';
6291
6292 -- 5.5 - Bug 5194761: delete records from wms_xdock_pegging_gtmp
6293 DELETE wms_xdock_pegging_gtmp;
6294 IF (l_debug = 1) AND SQL%FOUND THEN
6295 print_debug('5.5 - Cleared the temp table wms_xdock_pegging_gtmp');
6296 END IF;
6297
6298 -- Standard call to commit
6299 IF fnd_api.To_Boolean(p_commit) THEN
6300 COMMIT;
6301 END IF;
6302 l_progress := '620';
6303
6304 -- If we have reached this point, the return status should be set to success.
6305 -- This variable is reused each time we call another API but we try to continue with the
6306 -- flow and raise an exception only when absolutely necessary. Since this is a planning
6307 -- and pegging API, if exceptions occur, we should just not peg anything instead of throwing
6308 -- errors. Addendum to this is for allocation method of 'Crossdock Only', if any of the
6309 -- lines could not be crossdocked, return a 'Warning' status. This is so Shipping can alert
6310 -- the user that some lines were not able to be allocated through crossdock. The other
6311 -- allocation methods are taken care of when backordering unallocated WDD lines.
6312 IF (l_allocation_method = G_CROSSDOCK_ONLY AND l_unable_to_crossdock) THEN
6313 x_return_status := WSH_UTIL_CORE.G_RET_STS_WARNING;
6314 ELSE
6315 x_return_status := fnd_api.g_ret_sts_success;
6316 END IF;
6317 l_progress := '630';
6318
6319 end if; -- Simulation Mode
6320 IF (l_debug = 1) THEN
6321 print_debug('***End of Planned_Cross_Dock***');
6322 END IF;
6323
6324 -- Stop the profiler
6325 -- dbms_profiler.stop_profiler;
6326
6327 EXCEPTION
6328 WHEN FND_API.G_EXC_ERROR THEN
6329 ROLLBACK TO Planned_Cross_Dock_sp;
6330 x_return_status := fnd_api.g_ret_sts_error;
6331 fnd_msg_pub.count_and_get(p_count => x_msg_count,
6332 p_data => x_msg_data);
6333 IF (l_debug = 1) THEN
6334 print_debug('Exiting Planned_Cross_Dock - Execution error: ' ||
6335 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
6336 END IF;
6337
6338 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
6339 ROLLBACK TO Planned_Cross_Dock_sp;
6340 x_return_status := fnd_api.g_ret_sts_unexp_error;
6341 fnd_msg_pub.count_and_get(p_count => x_msg_count,
6342 p_data => x_msg_data);
6343 IF (l_debug = 1) THEN
6344 print_debug('Exiting Planned_Cross_Dock - Unexpected error: ' ||
6345 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
6346 END IF;
6347
6348 WHEN OTHERS THEN
6349 ROLLBACK TO Planned_Cross_Dock_sp;
6350 x_return_status := fnd_api.g_ret_sts_unexp_error;
6351 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6352 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6353 END IF;
6354 fnd_msg_pub.count_and_get(p_count => x_msg_count,
6355 p_data => x_msg_data);
6356 IF (l_debug = 1) THEN
6357 print_debug('Exiting Planned_Cross_Dock - Others exception: ' ||
6358 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
6359 END IF;
6360
6361 END Planned_Cross_Dock;
6362 -- {{ }}
6363 -- {{******************** End Planned_Cross_Dock ********************}}
6364 -- {{ }}
6365
6366
6367 -- {{ }}
6368 -- {{******************** Procedure Opportunistic_Cross_Dock ********************}}
6369 PROCEDURE Opportunistic_Cross_Dock
6370 (p_organization_id IN NUMBER,
6371 p_move_order_line_id IN NUMBER,
6372 p_crossdock_criterion_id IN NUMBER,
6373 x_return_status OUT NOCOPY VARCHAR2,
6374 x_msg_count OUT NOCOPY NUMBER,
6375 x_msg_data OUT NOCOPY VARCHAR2)
6376 IS
6377 l_api_name CONSTANT VARCHAR2(30) := 'Opportunistic_Cross_Dock';
6378 l_progress VARCHAR2(10);
6379 l_debug NUMBER := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6380
6381 -- This variable is used to indicate if the custom APIs were used.
6382 l_api_is_implemented BOOLEAN;
6383
6384 -- This variable stores the PJM org parameter to allow cross project allocation
6385 -- when matching supply to demand lines for crossdocking. Possible values are 'Y' or 'N'.
6386 l_allow_cross_proj_issues VARCHAR2(1);
6387
6388 -- This variable indicates if the org is PJM enabled or not. 1 = Yes, 2 = No
6389 l_project_ref_enabled NUMBER;
6390
6391 -- This boolean variable indicates if the org is a WMS org or not.
6392 l_wms_org_flag BOOLEAN;
6393
6394 -- These variable will store necessary info for the item being crossdocked
6395 -- from the MOL inputted.
6396 l_inventory_item_id NUMBER;
6397 l_primary_uom_code VARCHAR2(3);
6398 l_reservable_type NUMBER;
6399 l_lot_control_code NUMBER;
6400 l_lot_divisible_flag VARCHAR2(1);
6401
6402 -- Local variables for the input org and crossdock criteria.
6403 -- Needed so code from Planned Crossdock case can be reused.
6404 l_organization_id NUMBER;
6405 l_crossdock_criteria_id NUMBER;
6406
6407 -- Cursor to retrieve valid scheduled Sales Order demand lines
6408 CURSOR SO_scheduled_lines(p_project_id NUMBER, p_task_id NUMBER) IS
6409 SELECT
6410 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
6411 wdd.source_line_id AS line_id,
6412 wdd.delivery_detail_id AS line_detail_id,
6413 wdd.requested_quantity AS quantity,
6414 wdd.requested_quantity_uom AS uom_code,
6415 wdd.requested_quantity2 AS secondary_quantity,
6416 wdd.requested_quantity_uom2 AS secondary_uom_code,
6417 wdd.project_id AS project_id,
6418 wdd.task_id AS task_id,
6419 NULL AS wip_supply_type
6420 FROM wsh_delivery_details wdd, oe_order_lines_all ool
6421 WHERE wdd.organization_id = l_organization_id
6422 AND wdd.inventory_item_id = l_inventory_item_id
6423 AND wdd.released_status = 'R'
6424 AND wdd.source_code = 'OE'
6425 AND wdd.requested_quantity > 0
6426 AND wdd.source_line_id = ool.line_id
6427 AND NVL(ool.source_document_type_id, -999) <> 10
6428 AND ool.booked_flag = 'Y'
6429 AND ool.open_flag = 'Y'
6430 AND NVL(ool.fulfillment_base,'P') <> 'S' --16466246
6431 AND NOT EXISTS (SELECT 'Drop Ship'
6432 FROM oe_drop_ship_sources odss
6433 WHERE odss.header_id = ool.header_id
6434 AND odss.line_id = ool.line_id)
6435 -- Only pick up WDD lines that match the project/task of the MOL if necessary
6436 AND (l_project_ref_enabled = 2 OR
6437 l_allow_cross_proj_issues = 'Y' OR
6438 (NVL(wdd.project_id, -999) = NVL(p_project_id, -999) AND
6439 NVL(wdd.task_id, -999) = NVL(p_task_id, -999)));
6440
6441
6442 -- Cursor to retrieve valid backordered Sales Order demand lines
6443 CURSOR SO_backordered_lines(p_project_id NUMBER, p_task_id NUMBER) IS
6444 SELECT
6445 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
6446 wdd.source_line_id AS line_id,
6447 wdd.delivery_detail_id AS line_detail_id,
6448 wdd.requested_quantity AS quantity,
6449 wdd.requested_quantity_uom AS uom_code,
6450 wdd.requested_quantity2 AS secondary_quantity,
6451 wdd.requested_quantity_uom2 AS secondary_uom_code,
6452 wdd.project_id AS project_id,
6453 wdd.task_id AS task_id,
6454 NULL AS wip_supply_type
6455 FROM wsh_delivery_details wdd, oe_order_lines_all ool
6456 WHERE wdd.organization_id = l_organization_id
6457 AND wdd.inventory_item_id = l_inventory_item_id
6458 AND wdd.released_status = 'B'
6459 AND wdd.source_code = 'OE'
6460 AND wdd.requested_quantity > 0
6461 AND wdd.source_line_id = ool.line_id
6462 AND NVL(ool.source_document_type_id, -999) <> 10
6463 AND ool.booked_flag = 'Y'
6464 AND ool.open_flag = 'Y'
6465 AND NVL(ool.fulfillment_base,'P') <> 'S' --16466246
6466 AND NOT EXISTS (SELECT 'Drop Ship'
6467 FROM oe_drop_ship_sources odss
6468 WHERE odss.header_id = ool.header_id
6469 AND odss.line_id = ool.line_id)
6470 -- Only pick up WDD lines that match the project/task of the MOL if necessary
6471 AND (l_project_ref_enabled = 2 OR
6472 l_allow_cross_proj_issues = 'Y' OR
6473 (NVL(wdd.project_id, -999) = NVL(p_project_id, -999) AND
6474 NVL(wdd.task_id, -999) = NVL(p_task_id, -999)));
6475
6476
6477 -- Cursor to retrieve valid scheduled Internal Order demand lines
6478 CURSOR IO_scheduled_lines(p_project_id NUMBER, p_task_id NUMBER) IS
6479 SELECT
6480 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
6481 wdd.source_line_id AS line_id,
6482 wdd.delivery_detail_id AS line_detail_id,
6483 wdd.requested_quantity AS quantity,
6484 wdd.requested_quantity_uom AS uom_code,
6485 wdd.requested_quantity2 AS secondary_quantity,
6486 wdd.requested_quantity_uom2 AS secondary_uom_code,
6487 wdd.project_id AS project_id,
6488 wdd.task_id AS task_id,
6489 NULL AS wip_supply_type
6490 FROM wsh_delivery_details wdd, oe_order_lines_all ool
6491 WHERE wdd.organization_id = l_organization_id
6492 AND wdd.inventory_item_id = l_inventory_item_id
6493 AND wdd.released_status = 'R'
6494 AND wdd.source_code = 'OE'
6495 AND wdd.requested_quantity > 0
6496 AND wdd.source_line_id = ool.line_id
6497 AND NVL(ool.source_document_type_id, -999) = 10
6498 AND ool.booked_flag = 'Y'
6499 AND ool.open_flag = 'Y'
6500 AND NVL(ool.fulfillment_base,'P') <> 'S' --16466246
6501 AND NOT EXISTS (SELECT 'Drop Ship'
6502 FROM oe_drop_ship_sources odss
6503 WHERE odss.header_id = ool.header_id
6504 AND odss.line_id = ool.line_id)
6505 -- Only pick up WDD lines that match the project/task of the MOL if necessary
6506 AND (l_project_ref_enabled = 2 OR
6507 l_allow_cross_proj_issues = 'Y' OR
6508 (NVL(wdd.project_id, -999) = NVL(p_project_id, -999) AND
6509 NVL(wdd.task_id, -999) = NVL(p_task_id, -999)));
6510
6511
6512 -- Cursor to retrieve valid backordered Internal Order demand lines
6513 CURSOR IO_backordered_lines(p_project_id NUMBER, p_task_id NUMBER) IS
6514 SELECT
6515 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
6516 wdd.source_line_id AS line_id,
6517 wdd.delivery_detail_id AS line_detail_id,
6518 wdd.requested_quantity AS quantity,
6519 wdd.requested_quantity_uom AS uom_code,
6520 wdd.requested_quantity2 AS secondary_quantity,
6521 wdd.requested_quantity_uom2 AS secondary_uom_code,
6522 wdd.project_id AS project_id,
6523 wdd.task_id AS task_id,
6524 NULL AS wip_supply_type
6525 FROM wsh_delivery_details wdd, oe_order_lines_all ool
6526 WHERE wdd.organization_id = l_organization_id
6527 AND wdd.inventory_item_id = l_inventory_item_id
6528 AND wdd.released_status = 'B'
6529 AND wdd.source_code = 'OE'
6530 AND wdd.requested_quantity > 0
6531 AND wdd.source_line_id = ool.line_id
6532 AND NVL(ool.source_document_type_id, -999) = 10
6533 AND ool.booked_flag = 'Y'
6534 AND ool.open_flag = 'Y'
6535 AND NVL(ool.fulfillment_base,'P') <> 'S' --16466246
6536 AND NOT EXISTS (SELECT 'Drop Ship'
6537 FROM oe_drop_ship_sources odss
6538 WHERE odss.header_id = ool.header_id
6539 AND odss.line_id = ool.line_id)
6540 -- Only pick up WDD lines that match the project/task of the MOL if necessary
6541 AND (l_project_ref_enabled = 2 OR
6542 l_allow_cross_proj_issues = 'Y' OR
6543 (NVL(wdd.project_id, -999) = NVL(p_project_id, -999) AND
6544 NVL(wdd.task_id, -999) = NVL(p_task_id, -999)));
6545
6546
6547 -- Cursor to retrieve valid backordered WIP Component demand lines
6548 CURSOR wip_component_demand_lines(p_project_id NUMBER,
6549 p_task_id NUMBER,
6550 p_xdock_start_time DATE,
6551 p_xdock_end_time DATE) IS
6552 SELECT
6553 wmsv.wip_entity_id AS header_id,
6554 wmsv.operation_seq_num AS line_id,
6555 wmsv.repetitive_schedule_id AS line_detail_id,
6556 wmsv.date_required AS expected_time,
6557 wmsv.quantity_backordered AS quantity,
6558 wmsv.primary_uom_code AS uom_code,
6559 NULL AS secondary_quantity,
6560 NULL AS secondary_uom_code,
6561 wmsv.project_id AS project_id,
6562 wmsv.task_id AS task_id,
6563 wmsv.wip_supply_type AS wip_supply_type
6564 FROM wip_material_shortages_v wmsv
6565 WHERE wmsv.organization_id = l_organization_id
6566 AND wmsv.inventory_item_id = l_inventory_item_id
6567 AND wmsv.wip_entity_type in (1, 2, 5)
6568 AND wmsv.date_required IS NOT NULL
6569 -- Only pick up WIP demand lines that lie within the crossdock window
6570 -- OR have a date_required value in the past.
6571 AND (wmsv.date_required BETWEEN p_xdock_start_time AND p_xdock_end_time OR
6572 wmsv.date_required < SYSDATE)
6573 -- Only pick up WIP lines that match the project/task of the MOL if necessary
6574 AND (l_project_ref_enabled = 2 OR
6575 l_allow_cross_proj_issues = 'Y' OR
6576 (NVL(wmsv.project_id, -999) = NVL(p_project_id, -999) AND
6577 NVL(wmsv.task_id, -999) = NVL(p_task_id, -999)));
6578
6579
6580 -- Variables to retrieve the values from the demand lines cursors.
6581 -- We will bulk collect the records from the cursors into these PLSQL tables and
6582 -- use them to do a bulk insert into the xdock pegging global temp table.
6583 TYPE num_tab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
6584 TYPE uom_tab IS TABLE OF VARCHAR2(3) INDEX BY BINARY_INTEGER;
6585 TYPE bool_tab IS TABLE OF BOOLEAN INDEX BY BINARY_INTEGER;
6586 l_header_id_tb num_tab;
6587 l_line_id_tb num_tab;
6588 l_line_detail_id_tb num_tab;
6589 l_quantity_tb num_tab;
6590 l_uom_code_tb uom_tab;
6591 l_secondary_quantity_tb num_tab;
6592 l_secondary_uom_code_tb uom_tab;
6593 l_project_id_tb num_tab;
6594 l_task_id_tb num_tab;
6595 l_wip_supply_type_tb num_tab;
6596
6597 -- Variables to store the expected time values for the demand line records retrieved.
6598 -- We will use the date tables to do a bulk insert into the xdock pegging global temp table.
6599 TYPE date_tab IS TABLE OF DATE INDEX BY BINARY_INTEGER;
6600 l_dock_start_time_tb date_tab;
6601 l_dock_mean_time_tb date_tab;
6602 l_dock_end_time_tb date_tab;
6603 l_expected_time_tb date_tab;
6604
6605 -- Cursor to retrieve, lock and validate the MOL inputted
6606 CURSOR get_move_order_line IS
6607 SELECT mtrl.*,
6608 msi.primary_uom_code AS primary_uom_code,
6609 NVL(msi.reservable_type, 1) AS reservable_type,
6610 NVL(msi.lot_control_code, 1) AS lot_control_code,
6611 NVL(msi.lot_divisible_flag, 'Y') AS lot_divisible_flag,
6612 wlpn.lpn_context AS lpn_context
6613 FROM mtl_txn_request_lines mtrl, mtl_system_items msi, wms_license_plate_numbers wlpn
6614 WHERE mtrl.line_id = p_move_order_line_id
6615 AND mtrl.organization_id = l_organization_id
6616 -- Modified the line below to use an IN instead of <>
6617 -- AND mtrl.line_status <> inv_globals.g_to_status_closed
6618 AND mtrl.line_status IN (inv_globals.g_to_status_preapproved,
6619 inv_globals.g_to_status_approved)
6620 AND mtrl.backorder_delivery_detail_id IS NULL
6621 AND mtrl.lpn_id IS NOT NULL
6622 AND mtrl.quantity > 0
6623 AND NVL(mtrl.quantity_delivered, 0) = 0
6624 AND NVL(mtrl.quantity_detailed, 0) = 0
6625 AND NVL(mtrl.inspection_status, 2) = 2
6626 AND NVL(mtrl.wms_process_flag, 1) = 1
6627 AND NVL(mtrl.reference, 'non-RMA') <> 'ORDER_LINE_ID'
6628 AND mtrl.inventory_item_id = msi.inventory_item_id
6629 AND mtrl.organization_id = msi.organization_id
6630 AND mtrl.lpn_id = wlpn.lpn_id
6631 AND wlpn.lpn_context IN (2, 3) -- WIP or RCV
6632 -- Added the following line so the index: WMS_LICENSE_PLATE_NUMBERS_N6
6633 -- can be used in case the SQL optimizer uses WLPN as the driving table.
6634 AND wlpn.organization_id = l_organization_id
6635 FOR UPDATE OF mtrl.line_id NOWAIT;
6636
6637 -- Variable to store info from the inputted MOL record
6638 l_mol_rec get_move_order_line%ROWTYPE;
6639 l_supply_type_id NUMBER;
6640 l_supply_header_id NUMBER;
6641 l_supply_line_id NUMBER;
6642 l_supply_line_detail_id NUMBER;
6643 l_supply_uom_code VARCHAR2(3);
6644 l_supply_expected_time DATE;
6645 l_mol_qty NUMBER;
6646 l_mol_header_id NUMBER;
6647 l_mol_line_id NUMBER;
6648 l_mol_prim_qty NUMBER;
6649 l_mol_qty2 NUMBER;
6650 l_mol_uom_code2 VARCHAR2(3);
6651 l_mol_lpn_id NUMBER;
6652
6653 -- Cursor to lock the set of MOL lines related to the input MOL (i.e. same org/item
6654 -- for RCV, same org/item/WIP job for WIP)
6655 CURSOR lock_mo_lines(p_lpn_context NUMBER,
6656 p_wip_entity_id NUMBER,
6657 p_operation_seq_num NUMBER,
6658 p_repetitive_schedule_id NUMBER) IS
6659 SELECT mtrl.line_id
6660 FROM mtl_txn_request_lines mtrl, mtl_txn_request_headers mtrh,
6661 wms_license_plate_numbers wlpn
6662 WHERE mtrl.header_id = mtrh.header_id
6663 AND mtrh.move_order_type = inv_globals.g_move_order_put_away
6664 AND mtrl.organization_id = l_organization_id
6665 AND mtrl.inventory_item_id = l_inventory_item_id
6666 -- Modified the line below to use an IN instead of <> so the
6667 -- index MTL_TXN_REQUEST_LINES_N10 on MTRL is more likely to be used.
6668 -- AND mtrl.line_status <> inv_globals.g_to_status_closed
6669 AND mtrl.line_status IN (inv_globals.g_to_status_preapproved,
6670 inv_globals.g_to_status_approved)
6671 AND mtrl.backorder_delivery_detail_id IS NULL
6672 AND mtrl.lpn_id IS NOT NULL
6673 AND mtrl.quantity > 0
6674 AND NVL(mtrl.quantity_delivered, 0) = 0
6675 AND NVL(mtrl.quantity_detailed, 0) = 0
6676 AND NVL(mtrl.inspection_status, 2) = 2
6677 AND NVL(mtrl.wms_process_flag, 1) = 1
6678 AND NVL(mtrl.reference, 'non-RMA') <> 'ORDER_LINE_ID'
6679 AND mtrl.lpn_id = wlpn.lpn_id
6680 AND wlpn.lpn_context = p_lpn_context
6681 -- Added the following line so the index: WMS_LICENSE_PLATE_NUMBERS_N6
6682 -- can be used in case the SQL optimizer uses WLPN as the driving table.
6683 AND wlpn.organization_id = l_organization_id
6684 AND (p_lpn_context = 3 OR -- RCV
6685 (p_lpn_context = 2 AND -- WIP
6686 mtrl.txn_source_id = p_wip_entity_id)
6687 -- The two lines below are not required since WIP putaway MOLs do not store
6688 -- the operation sequence num or the repetitive schedule ID.
6689 -- NVL(mtrl.txn_source_line_id, -999) = NVL(p_operation_seq_num, -999) AND
6690 -- NVL(mtrl.reference_id, -999) = NVL(p_repetitive_schedule_id, -999))
6691 )
6692 FOR UPDATE OF mtrl.line_id NOWAIT;
6693
6694 -- Table to store the results from the lock_mo_lines cursor
6695 TYPE locked_mo_lines_tb IS TABLE OF lock_mo_lines%ROWTYPE INDEX BY BINARY_INTEGER;
6696 l_locked_mo_lines_tb locked_mo_lines_tb;
6697
6698 -- Crossdock Criteria time interval values.
6699 -- The max precision for the DAY is 2 digits (i.e. 99 DAY is the largest possible value)
6700 -- and will be enforced in the crossdock criteria definition form.
6701 l_xdock_window_interval INTERVAL DAY(2) TO SECOND;
6702 l_buffer_interval INTERVAL DAY(2) TO SECOND;
6703 l_processing_interval INTERVAL DAY(2) TO SECOND;
6704
6705 -- Crossdock time window start and end times. Any valid deamnds within this
6706 -- time interval are valid for crossdocking.
6707 l_xdock_start_time DATE;
6708 l_xdock_end_time DATE;
6709
6710 -- Cursor to retrieve the existing high level non-crossdocked, non-WIP as demand reservations
6711 -- for the MO supply line. For these types of reservations, the detailed_quantity
6712 -- column should be NULL or 0.
6713 -- We will also lock the reservations records here. Using the SKIP LOCKED keyword,
6714 -- we can select only row records which are lockable without erroring out the entire query.
6715 CURSOR existing_rsvs_cursor(p_lpn_context NUMBER,
6716 p_wip_entity_id NUMBER) IS
6717 SELECT reservation_id, demand_source_type_id, demand_source_header_id,
6718 demand_source_line_id, reservation_quantity, reservation_uom_code,
6719 secondary_reservation_quantity, secondary_uom_code,
6720 primary_reservation_quantity, primary_uom_code
6721 FROM mtl_reservations
6722 WHERE organization_id = l_organization_id
6723 AND inventory_item_id = l_inventory_item_id
6724 AND ((p_lpn_context = 3 AND -- RCV supply
6725 supply_source_type_id = inv_reservation_global.g_source_type_rcv)
6726 OR
6727 (p_lpn_context = 2 AND -- WIP supply
6728 supply_source_type_id = inv_reservation_global.g_source_type_wip AND
6729 supply_source_header_id = p_wip_entity_id))
6730 AND demand_source_type_id <> inv_reservation_global.g_source_type_wip
6731 AND demand_source_line_detail IS NULL
6732 AND NVL(crossdock_flag, 'N') = 'N'
6733 AND primary_reservation_quantity - NVL(detailed_quantity, 0) > 0
6734 FOR UPDATE SKIP LOCKED;
6735
6736 -- Table to store the results from the existing reservations cursor
6737 TYPE existing_rsvs_tb IS TABLE OF existing_rsvs_cursor%ROWTYPE INDEX BY BINARY_INTEGER;
6738 l_existing_rsvs_tb existing_rsvs_tb;
6739
6740 -- Index used to loop through the existing high level non-inventory reservations
6741 l_rsv_index NUMBER;
6742
6743 -- Variables for existing reservations and the related demand line on it
6744 l_rsv_id NUMBER;
6745 l_rsv_qty NUMBER;
6746 l_rsv_uom_code VARCHAR2(3);
6747 l_rsv_qty2 NUMBER;
6748 l_rsv_uom_code2 VARCHAR2(3);
6749 l_rsv_prim_qty NUMBER;
6750 l_rsv_prim_uom_code VARCHAR2(3);
6751 l_demand_type_id NUMBER;
6752 l_demand_header_id NUMBER; -- OE order header ID
6753 l_demand_so_header_id NUMBER; -- Sales order header ID
6754 l_demand_line_id NUMBER;
6755
6756 -- Cursor to retrieve the valid WDD lines tied to an order line in an existing reservation.
6757 -- We will try to match for the project/task values on the supply line if necessary.
6758 CURSOR reserved_wdd_lines(p_project_id NUMBER, p_task_id NUMBER) IS
6759 SELECT wdd.delivery_detail_id, wdd.requested_quantity, wdd.requested_quantity_uom,
6760 wdd.requested_quantity2, wdd.requested_quantity_uom2,
6761 wdd.released_status, wdd.project_id, wdd.task_id
6762 FROM wsh_delivery_details wdd, oe_order_lines_all ool
6763 WHERE wdd.organization_id = l_organization_id
6764 AND wdd.inventory_item_id = l_inventory_item_id
6765 AND wdd.released_status IN ('R', 'B')
6766 AND wdd.source_code = 'OE'
6767 AND wdd.requested_quantity > 0
6768 AND wdd.source_header_id = l_demand_header_id
6769 AND wdd.source_line_id = l_demand_line_id
6770 AND wdd.source_line_id = ool.line_id
6771 AND ool.booked_flag = 'Y'
6772 AND ool.open_flag = 'Y'
6773 AND NOT EXISTS (SELECT 'Drop Ship'
6774 FROM oe_drop_ship_sources odss
6775 WHERE odss.header_id = ool.header_id
6776 AND odss.line_id = ool.line_id)
6777 -- Only pick up WDD lines that match the project/task of the MOL if necessary
6778 AND (l_project_ref_enabled = 2 OR
6779 l_allow_cross_proj_issues = 'Y' OR
6780 (NVL(wdd.project_id, -999) = NVL(p_project_id, -999) AND
6781 NVL(wdd.task_id, -999) = NVL(p_task_id, -999)))
6782 FOR UPDATE OF wdd.delivery_detail_id SKIP LOCKED;
6783
6784 -- Table to store the results from the reserved_wdd_lines cursor
6785 TYPE reserved_wdd_lines_tb IS TABLE OF reserved_wdd_lines%ROWTYPE INDEX BY BINARY_INTEGER;
6786 l_reserved_wdd_lines_tb reserved_wdd_lines_tb;
6787
6788 -- Index used to loop through the reserved WDD lines table
6789 l_wdd_index NUMBER;
6790
6791 -- Variables for the current demand line
6792 l_demand_line_detail_id NUMBER;
6793 l_demand_qty NUMBER;
6794 l_demand_uom_code VARCHAR2(3);
6795 l_demand_qty2 NUMBER;
6796 l_demand_uom_code2 VARCHAR2(3);
6797 l_demand_status VARCHAR2(1);
6798 l_demand_project_id NUMBER;
6799 l_demand_task_id NUMBER;
6800 l_dock_start_time DATE;
6801 l_dock_mean_time DATE;
6802 l_dock_end_time DATE;
6803 l_demand_expected_time DATE;
6804
6805 -- Variable used to store the current demand source code (as used by crossdock criteria)
6806 -- The supply source codes are different for Reservations and Crossdock Criteria.
6807 l_demand_src_code NUMBER;
6808
6809 -- Conversion rate when converting quantity values to different UOMs
6810 l_conversion_rate NUMBER;
6811 -- The standard Inventory precision is to 5 decimal places. Define this in a local constant
6812 -- in case this needs to be changed later on. Variable is used to round off converted values
6813 -- to this precision level.
6814 l_conversion_precision CONSTANT NUMBER := 5;
6815
6816 -- Variables to store the converted quantity values and the available to detail
6817 -- values. They will all be converted to the UOM on the MOL supply line, l_supply_uom_code.
6818 -- We also need the ATD qty in the primary UOM of the item.
6819 -- l_wdd_atr_txn_qty is used when the full quantity on the WDD line may not be available
6820 -- for crossdocking. This is not the case for existing reservations but is possible for
6821 -- normal crossdocking, i.e. other existing reservations tying up quantity on the WDD line.
6822 l_wdd_txn_qty NUMBER;
6823 l_wdd_atr_txn_qty NUMBER;
6824 l_rsv_txn_qty NUMBER;
6825 l_atd_qty NUMBER;
6826 l_atd_prim_qty NUMBER;
6827
6828 -- These values will store the available to detail quantity converted to the UOM of
6829 -- the WDD and RSV record respectively. They are used whenever those records need
6830 -- to be split. The secondary quantities are needed too when splitting a WDD or RSV record.
6831 -- For MOL records, the ATD quantity is always in that UOM. However, we still need to
6832 -- convert the ATD quantity to the secondary UOM on the MOL record if it exists.
6833 l_atd_wdd_qty NUMBER;
6834 l_atd_wdd_qty2 NUMBER;
6835 l_atd_rsv_qty NUMBER;
6836 l_atd_rsv_qty2 NUMBER;
6837 l_atd_mol_qty2 NUMBER;
6838
6839 -- Variables used to call the Shipping API to split a WDD line if a partial quantity
6840 -- is crossdocked on the WDD line.
6841 l_detail_id_tab WSH_UTIL_CORE.id_tab_type;
6842 l_action_prms WSH_GLBL_VAR_STRCT_GRP.dd_action_parameters_rec_type;
6843 l_action_out_rec WSH_GLBL_VAR_STRCT_GRP.dd_action_out_rec_type;
6844 l_split_wdd_rel_rec WSH_PR_CRITERIA.relRecTyp;
6845 l_split_wdd_id NUMBER;
6846 l_index NUMBER;
6847
6848 -- Variables used to call the Shipping API to update a WDD line when it is
6849 -- being crossdocked.
6850 l_detail_info_tab WSH_INTERFACE_EXT_GRP.Delivery_Details_Attr_Tbl_Type;
6851 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
6852 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
6853
6854 -- Variable used to update a crossdocked WDD record
6855 l_xdocked_wdd_index NUMBER;
6856
6857 -- Dummy variables used when calling the private Crossdock_WDD procedure.
6858 -- These are variables used in the Planned Crossdocking case but not needed here.
6859 l_batch_id NUMBER;
6860 l_wsh_release_table WSH_PR_CRITERIA.relRecTabTyp;
6861 l_trolin_delivery_ids WSH_UTIL_CORE.Id_Tab_Type;
6862 l_del_detail_id WSH_PICK_LIST.DelDetTabTyp;
6863 l_dummy_wdd_index NUMBER;
6864 l_allocation_method VARCHAR2(1);
6865 l_split_wdd_index NUMBER;
6866 l_split_delivery_index NUMBER;
6867 TYPE orig_wdd_values_rec IS RECORD
6868 (requested_quantity NUMBER,
6869 requested_quantity2 NUMBER,
6870 released_status VARCHAR2(1),
6871 move_order_line_id NUMBER);
6872 l_orig_wdd_values_rec orig_wdd_values_rec;
6873 l_error_code VARCHAR2(3);
6874
6875 -- Variables to split and update reservations records
6876 l_original_rsv_rec inv_reservation_global.mtl_reservation_rec_type;
6877 l_to_rsv_rec inv_reservation_global.mtl_reservation_rec_type;
6878 l_original_serial_number inv_reservation_global.serial_number_tbl_type;
6879 l_to_serial_number inv_reservation_global.serial_number_tbl_type;
6880 l_split_rsv_id NUMBER;
6881
6882 -- Variables to store the available to reserve quantity for a demand or supply line
6883 -- both in the primary and demand/supply line UOM.
6884 l_demand_atr_prim_qty NUMBER;
6885 l_demand_atr_qty NUMBER;
6886 l_demand_available_qty NUMBER;
6887 l_supply_atr_prim_qty NUMBER;
6888 l_supply_atr_qty NUMBER;
6889 l_supply_available_qty NUMBER;
6890
6891 -- Cursor to retrieve eligible demand source types for a given crossdock criteria
6892 CURSOR demand_src_types_cursor IS
6893 SELECT source_code
6894 FROM wms_xdock_source_assignments
6895 WHERE criterion_id = l_crossdock_criteria_id
6896 AND source_type = G_SRC_TYPE_DEM
6897 ORDER BY priority;
6898
6899 -- Table to retrieve the values from the demand_src_types_cursor
6900 l_demand_src_types_tb num_tab;
6901
6902 -- Table to store the valid demand lines for crossdocking for the MOL supply line.
6903 -- The type is defined in the specs instead so the custom logic package can reference it.
6904 l_shopping_basket_tb shopping_basket_tb;
6905
6906 -- Variables used when calling custom logic to sort the supply lines in the
6907 -- shopping basket table.
6908 l_sorted_order_tb sorted_order_tb;
6909 l_shopping_basket_temp_tb shopping_basket_tb;
6910 l_indices_used_tb bool_tab;
6911
6912 -- Variables for the get_demand_lines cursor to indicate the relative priority of the demand
6913 -- source types to retrieve valid demand lines for. If we don't need to prioritize documents,
6914 -- a default value of 99 will be used. The cursor get_demand_lines will order by the priority
6915 -- value in ascending order so lower values have higher priority.
6916 l_so_sched_priority NUMBER;
6917 l_so_back_priority NUMBER;
6918 l_io_sched_priority NUMBER;
6919 l_io_back_priority NUMBER;
6920 l_wip_priority NUMBER;
6921
6922 -- Cursor to retrieve valid demand lines for crossdocking.
6923 -- For opportunistic crossdock, only crossdockable demand lines are inserted into
6924 -- the global temp table. Therefore we want to select every single record (full table scan)
6925 -- from wms_xdock_pegging_gtmp.
6926 CURSOR get_demand_lines(p_crossdock_goal NUMBER,
6927 p_so_sched_priority NUMBER,
6928 p_so_back_priority NUMBER,
6929 p_io_sched_priority NUMBER,
6930 p_io_back_priority NUMBER,
6931 p_wip_priority NUMBER) IS
6932 SELECT ROWID,
6933 inventory_item_id,
6934 xdock_source_code,
6935 source_type_id,
6936 source_header_id,
6937 source_line_id,
6938 source_line_detail_id,
6939 dock_start_time,
6940 dock_mean_time,
6941 dock_end_time,
6942 expected_time,
6943 quantity,
6944 reservable_quantity,
6945 uom_code,
6946 primary_quantity,
6947 secondary_quantity,
6948 secondary_uom_code,
6949 project_id,
6950 task_id,
6951 lpn_id,
6952 wip_supply_type
6953 FROM wms_xdock_pegging_gtmp
6954 WHERE inventory_item_id = l_inventory_item_id
6955 ORDER BY DECODE (xdock_source_code,
6956 G_OPP_DEM_SO_SCHED, p_so_sched_priority,
6957 G_OPP_DEM_SO_BKORD, p_so_back_priority,
6958 G_OPP_DEM_IO_SCHED, p_io_sched_priority,
6959 G_OPP_DEM_IO_BKORD, p_io_back_priority,
6960 G_OPP_DEM_WIP_BKORD, p_wip_priority,
6961 99),
6962 DECODE (p_crossdock_goal,
6963 G_MINIMIZE_WAIT, SYSDATE - expected_time,
6964 G_MAXIMIZE_XDOCK, expected_time - SYSDATE,
6965 G_CUSTOM_GOAL, NULL,
6966 NULL);
6967
6968 -- Index used to loop through the demand lines for crossdocking to the MOL supply line.
6969 l_demand_index NUMBER;
6970
6971 -- Cursor to lock the WDD demand record
6972 CURSOR lock_wdd_record(p_delivery_detail_id NUMBER) IS
6973 SELECT delivery_detail_id
6974 FROM wsh_delivery_details
6975 WHERE delivery_detail_id = p_delivery_detail_id
6976 FOR UPDATE NOWAIT;
6977
6978 -- Cursor to lock the WIP demand record.
6979 -- WIP backordered component demand MUST have a record in the table
6980 -- wip_requirement_operations. Thus, operation_seq_num should not be null.
6981 -- We could also lock the wip_entities record but that is probably not necessary,
6982 -- especially if the demand is a WIP Repetitive job. That might lock up the record
6983 -- unnecessarily for other repetitive jobs with the same wip_entity_id.
6984 CURSOR lock_wip_record(p_wip_entity_id NUMBER,
6985 p_operation_seq_num NUMBER,
6986 p_repetitive_schedule_id NUMBER) IS
6987 SELECT wip_entity_id
6988 FROM wip_requirement_operations
6989 WHERE inventory_item_id = l_inventory_item_id
6990 AND organization_id = l_organization_id
6991 AND wip_entity_id = p_wip_entity_id
6992 AND operation_seq_num = p_operation_seq_num
6993 AND NVL(repetitive_schedule_id, -999) = NVL(p_repetitive_schedule_id, -999)
6994 FOR UPDATE NOWAIT;
6995
6996 -- The following are variables used to call the create_reservation API
6997 l_quantity_reserved NUMBER;
6998 l_quantity_reserved2 NUMBER;
6999
7000 -- Variables used for WIP backordered component demand lines
7001 l_wip_entity_id NUMBER;
7002 l_operation_seq_num NUMBER;
7003 l_repetitive_schedule_id NUMBER;
7004 l_wip_supply_type NUMBER;
7005 l_wip_qty_allocated NUMBER;
7006
7007 -- Cursor used when satisfying existing reservations with WIP as a supply.
7008 -- Part of the reservation could already be fulfilled by other MOLs from the same
7009 -- WIP job that have been crossdocked. Since we do not split and update the WIP
7010 -- to SO/IO reservation when crossdocking, and if the crossdocked MOLs have not
7011 -- been delivered yet, the WIP reservation will not be updated. We need to take
7012 -- these crossdocked WIP MOLs into account when calculating the quantity left to
7013 -- satisfy on the reservation. Query for crossdocked WIP MOLs with the WIP job on
7014 -- the reservation as supply and Order Line on reservation as demand.
7015 CURSOR get_wip_xdock_qty(p_wip_entity_id NUMBER,
7016 p_operation_seq_num NUMBER,
7017 p_repetitive_schedule_id NUMBER,
7018 p_demand_source_header_id NUMBER,
7019 p_demand_source_line_id NUMBER) IS
7020 SELECT NVL(SUM(mtrl.primary_quantity), 0)
7021 FROM mtl_txn_request_lines mtrl, wsh_delivery_details wdd,
7022 wms_license_plate_numbers wlpn
7023 WHERE mtrl.organization_id = l_organization_id
7024 AND mtrl.inventory_item_id = l_inventory_item_id
7025 -- Modified the line below to use an IN instead of <> so the
7026 -- index MTL_TXN_REQUEST_LINES_N10 on MTRL is more likely to be used.
7027 -- AND mtrl.line_status <> inv_globals.g_to_status_closed
7028 AND mtrl.line_status IN (inv_globals.g_to_status_preapproved,
7029 inv_globals.g_to_status_approved)
7030 AND NVL(mtrl.quantity_delivered, 0) = 0
7031 AND mtrl.txn_source_id = p_wip_entity_id
7032 -- The two lines below are not required since WIP putaway MOLs do not store
7033 -- the operation sequence num or the repetitive schedule ID.
7034 -- AND NVL(mtrl.txn_source_line_id, -999) = NVL(p_operation_seq_num, -999)
7035 -- AND NVL(mtrl.reference_id, -999) = NVL(p_repetitive_schedule_id, -999)
7036 AND mtrl.lpn_id = wlpn.lpn_id
7037 AND wlpn.lpn_context = 2 -- WIP
7038 -- Added the following line so the index: WMS_LICENSE_PLATE_NUMBERS_N6
7039 -- can be used in case the SQL optimizer uses WLPN as the driving table.
7040 AND wlpn.organization_id = l_organization_id
7041 AND mtrl.crossdock_type = 1 -- Crossdocked to OE demand
7042 AND mtrl.backorder_delivery_detail_id = wdd.delivery_detail_id
7043 AND wdd.source_header_id = p_demand_source_header_id
7044 AND wdd.source_line_id = p_demand_source_line_id;
7045
7046 -- Variables to WIP crossdocked quantity values to adjust the reservation qty
7047 l_wip_xdock_prim_qty NUMBER;
7048 l_wip_xdock_qty NUMBER;
7049 l_wip_xdock_qty2 NUMBER;
7050
7051 -- Variable for WIP MOL supply lines to indicate what type of WIP job
7052 -- it is from, i.e. Discrete or Flow.
7053 l_wip_entity_type NUMBER;
7054
7055 -- For WIP Discrete Job MOLs, check to see if multiple reservations exist
7056 -- for the same WIP job as supply. If so, then do not crossdock the MOL.
7057 -- If one reservation exists, try to honor it if the demand is of type OE.
7058 -- Any quantity left can only be pegged to this same OE demand. We do not want
7059 -- to create multiple reservations for the same WIP job going to different demands.
7060 -- Use a distinct in case we have multiple reservations for the same WIP supply and
7061 -- demand. This could be possible if the reservations have a different requirement date
7062 -- so the reservations were not merged.
7063 CURSOR existing_wip_rsvs IS
7064 SELECT DISTINCT demand_source_type_id, demand_source_header_id, demand_source_line_id
7065 FROM mtl_reservations
7066 WHERE organization_id = l_organization_id
7067 AND inventory_item_id = l_inventory_item_id
7068 AND supply_source_type_id = inv_reservation_global.g_source_type_wip
7069 AND supply_source_header_id = l_supply_header_id;
7070
7071 -- Table to store the results from the existing WIP reservations cursor
7072 TYPE existing_wip_rsvs_tb IS TABLE OF existing_wip_rsvs%ROWTYPE INDEX BY BINARY_INTEGER;
7073 l_existing_wip_rsvs_tb existing_wip_rsvs_tb;
7074
7075 -- Variables to store the demand that a WIP MOL supply should be pegged against
7076 l_wip_demand_type_id NUMBER;
7077 l_wip_demand_header_id NUMBER; -- MTL Sales Order Header ID from Reservations
7078 l_wip_demand_line_id NUMBER;
7079 l_new_mol_id number;
7080 BEGIN
7081 -- Start the profiler for Unit Testing to ensure complete code coverage
7082 --dbms_profiler.start_profiler('Opportunistic_Cross_Dock: ' || p_move_order_line_id);
7083
7084 IF (l_debug = 1) THEN
7085 print_debug('***Calling Opportunistic_Cross_Dock with the following parameters***');
7086 print_debug('Package Version: ==========> ' || g_pkg_version);
7087 print_debug('p_organization_id: ========> ' || p_organization_id);
7088 print_debug('p_move_order_line_id: =====> ' || p_move_order_line_id);
7089 print_debug('p_crossdock_criterion_id: => ' || p_crossdock_criterion_id);
7090 END IF;
7091
7092 -- Set the savepoint
7093 SAVEPOINT Opportunistic_Cross_Dock_sp;
7094 l_progress := '10';
7095
7096 -- Initialize message list to clear any existing messages
7097 fnd_msg_pub.initialize;
7098 l_progress := '20';
7099
7100 -- Initialize API return status to success
7101 x_return_status := fnd_api.g_ret_sts_success;
7102 l_progress := '30';
7103
7104 -- Initialize local versions of the following input parameters
7105 l_organization_id := p_organization_id;
7106 l_crossdock_criteria_id := p_crossdock_criterion_id;
7107
7108 -- Initialize the PLSQL tables used to retrieve the demand line cursor records
7109 l_header_id_tb.DELETE;
7110 l_line_id_tb.DELETE;
7111 l_line_detail_id_tb.DELETE;
7112 l_quantity_tb.DELETE;
7113 l_uom_code_tb.DELETE;
7114 l_secondary_quantity_tb.DELETE;
7115 l_secondary_uom_code_tb.DELETE;
7116 l_project_id_tb.DELETE;
7117 l_task_id_tb.DELETE;
7118 l_dock_start_time_tb.DELETE;
7119 l_dock_mean_time_tb.DELETE;
7120 l_dock_end_time_tb.DELETE;
7121 l_expected_time_tb.DELETE;
7122 l_wip_supply_type_tb.DELETE;
7123
7124 -- Initialize the detail info table used for updating
7125 -- crossdocked WDD records
7126 l_detail_info_tab.DELETE;
7127
7128 -- Initialize the global Item UOM conversion table.
7129 g_item_uom_conversion_tb.DELETE;
7130 l_progress := '40';
7131
7132 -- Query for and cache the org record.
7133 IF (NOT INV_CACHE.set_org_rec(l_organization_id)) THEN
7134 IF (l_debug = 1) THEN
7135 print_debug('Error caching the org record');
7136 END IF;
7137 RAISE fnd_api.g_exc_unexpected_error;
7138 END IF;
7139 -- Set the PJM enabled flag.
7140 l_project_ref_enabled := INV_CACHE.org_rec.project_reference_enabled;
7141 l_progress := '50';
7142
7143 -- Check if the organization is a WMS organization
7144 l_wms_org_flag := wms_install.check_install
7145 (x_return_status => x_return_status,
7146 x_msg_count => x_msg_count,
7147 x_msg_data => x_msg_data,
7148 p_organization_id => l_organization_id);
7149 IF (x_return_status <> fnd_api.g_ret_sts_success) THEN
7150 IF (l_debug = 1) THEN
7151 print_debug('Call to wms_install.check_install failed: ' || x_msg_data);
7152 END IF;
7153 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7154 END IF;
7155 l_progress := '60';
7156
7157 -- Retrieve the org parameter for allowing cross project allocation for crossdocking.
7158 -- For now, just hardcode this to 'N'. The reason is even if we create a peg with
7159 -- differing project/task combinations, execution needs to be able to handle this.
7160 -- A project/task transfer needs to be done so until that code is present, we should not
7161 -- create cross project pegs. The following is the SQL for retrieving this value.
7162 /*IF (l_project_ref_enabled = 1) THEN
7163 -- PJM org so see if cross project allocation is allowed
7164 BEGIN
7165 SELECT NVL(allow_cross_proj_issues, 'N')
7166 INTO l_allow_cross_proj_issues
7167 FROM pjm_org_parameters
7168 WHERE organization_id = l_organization_id;
7169 EXCEPTION
7170 WHEN OTHERS THEN
7171 l_allow_cross_proj_issues := 'N';
7172 END;
7173 ELSE
7174 -- Non-PJM org so cross project allocation is allowed since there are no projects or tasks
7175 l_allow_cross_proj_issues := 'Y';
7176 END IF;*/
7177 l_allow_cross_proj_issues := 'N';
7178 l_progress := '70';
7179
7180 -- Query for and cache the crossdock criteria record for the value entered.
7181 -- A value must exist.
7182 -- {{
7183 -- API should error out if invalid crossdock criteria is passed. }}
7184 IF (NOT set_crossdock_criteria(l_crossdock_criteria_id)) THEN
7185 IF (l_debug = 1) THEN
7186 print_debug('Error caching the crossdock criteria record: ' ||
7187 l_crossdock_criteria_id);
7188 END IF;
7189 RAISE fnd_api.g_exc_unexpected_error;
7190 END IF;
7191 -- Validate that the crossdock criterion is of type 'Opportunistic'
7192 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).criterion_type <> G_CRT_TYPE_OPP) THEN
7193 IF (l_debug = 1) THEN
7194 print_debug('Invalid crossdock criterion type: ' ||
7195 g_crossdock_criteria_tb(l_crossdock_criteria_id).criterion_type);
7196 END IF;
7197 RAISE fnd_api.g_exc_unexpected_error;
7198 END IF;
7199 l_progress := '80';
7200 -- End of validations and initializations
7201
7202
7203 -- Section 1: Supply line validations and initializations
7204 -- 1.1 - Validate that the supply line is eligible for crossdocking.
7205 -- 1.2 - Lock the set of MOLs related to the inputted supply line.
7206 -- 1.3 - Calculate the crossdock window given the crossdock criteria time parameters.
7207
7208 -- 1.1 - Validate that the supply line is eligible for crossdocking.
7209 -- Retrieve, lock, and validate the MOL record.
7210 -- {{
7211 -- Invalid MOL supply lines should not be crossdocked. Test for MOLs that are
7212 -- already crossdocked, have partial quantity detailed or delivered already, loose non-LPN
7213 -- material, part of an RMA return, requires inspection and not inspected yet,
7214 -- or MOL has already been locked by some other process. }}
7215 BEGIN
7216 OPEN get_move_order_line;
7217 FETCH get_move_order_line INTO l_mol_rec;
7218 -- If the MOL record is not found, do not error out. Skip to the end
7219 -- and do not crossdock the MOL.
7220 IF (get_move_order_line%NOTFOUND) THEN
7221 IF (l_debug = 1) THEN
7222 print_debug('1.1 - MOL inputted is not valid for crossdocking');
7223 END IF;
7224 CLOSE get_move_order_line;
7225 GOTO end_crossdock;
7226 END IF;
7227 CLOSE get_move_order_line;
7228 EXCEPTION
7229 WHEN OTHERS THEN
7230 IF (l_debug = 1) THEN
7231 print_debug('1.1 - Could not retrieve the MOL record');
7232 END IF;
7233 -- If an exception occurs, do not error out.
7234 -- Skip to the end and do not crossdock the MOL.
7235 GOTO end_crossdock;
7236 END;
7237 IF (l_debug = 1) THEN
7238 print_debug('1.1 - Successfully retrieved the MOL record');
7239 print_debug('1.1 - Item ID: ==> ' || l_mol_rec.inventory_item_id);
7240 print_debug('1.1 - Quantity: => ' || l_mol_rec.quantity || ' ' || l_mol_rec.uom_code);
7241 END IF;
7242 l_progress := '90';
7243
7244 -- Store relevant values needed from the MOL record
7245 -- {{
7246 -- Crossdock WIP and RCV MOL supply lines. }}
7247 IF (l_mol_rec.lpn_context = 3) THEN
7248 -- RCV MOL
7249 l_supply_type_id := 27;
7250 l_supply_header_id := l_mol_rec.header_id;
7251 l_supply_line_id := l_mol_rec.line_id;
7252 l_supply_line_detail_id := NULL;
7253 ELSE
7254 -- WIP MOL
7255 l_supply_type_id := 5;
7256 l_supply_header_id := l_mol_rec.txn_source_id; -- WIP entity ID
7257 l_supply_line_id := l_mol_rec.txn_source_line_id; -- WIP oper seq num
7258 l_supply_line_detail_id := l_mol_rec.reference_id; -- WIP repetitive sched ID
7259 -- Actually the value above refers to the WIP LPN Completion header ID.
7260 -- For WIP job completions that are available for crossdocking (as a supply),
7261 -- only Discrete and Flow/WOL entity types will create a putaway MOL.
7262 -- I believe the only info about the WIP job that is populated on the MOL is
7263 -- the WIP entity ID, along with the LPN Completion header ID.
7264 -- For WIP MOLs, the supply line ID and supply line detail ID are not used currently
7265 -- in either the Availability check, or the create reservations call.
7266 -- It should be safe for now to leave these values as is.
7267
7268 -- Get the WIP entity type for the WIP supply
7269 BEGIN
7270 SELECT entity_type
7271 INTO l_wip_entity_type
7272 FROM wip_entities
7273 WHERE wip_entity_id = l_supply_header_id
7274 AND organization_id = l_organization_id;
7275 EXCEPTION
7276 WHEN OTHERS THEN
7277 IF (l_debug = 1) THEN
7278 print_debug('1.1 - Error retrieving WIP entity type for WIP entity: ' ||
7279 l_supply_header_id);
7280 END IF;
7281 -- If an exception occurs, just skip to the end and do not crossdock
7282 -- the MOL supply line.
7283 GOTO end_crossdock;
7284 END;
7285 END IF;
7286 IF (l_debug = 1) THEN
7287 print_debug('1.1 - Supply type: ========> ' || l_supply_type_id);
7288 print_debug('1.1 - Supply header ID: ===> ' || l_supply_header_id);
7289 print_debug('1.1 - Supply line ID: =====> ' || l_supply_line_id);
7290 print_debug('1.1 - Supply line detail: => ' || l_supply_line_detail_id);
7291 print_debug('1.1 - WIP entity type: ====> ' || l_wip_entity_type);
7292 END IF;
7293 l_progress := '95';
7294
7295 -- Check that for WIP MOL supply lines, the WIP entity type
7296 -- must be 1 (Discrete) or 4 (Flow). Other WIP entity types are
7297 -- not supported for crossdocking in R12.
7298 IF (l_wip_entity_type IS NOT NULL AND l_wip_entity_type NOT IN (1, 4)) THEN
7299 IF (l_debug = 1) THEN
7300 print_debug('1.1 - Invalid WIP entity type for crossdocking!');
7301 END IF;
7302 GOTO end_crossdock;
7303 END IF;
7304 l_progress := '97';
7305
7306 -- Store necessary info from the MOL record
7307 l_supply_uom_code := l_mol_rec.uom_code;
7308 l_supply_expected_time := SYSDATE;
7309 l_mol_header_id := l_mol_rec.header_id;
7310 l_mol_line_id := l_mol_rec.line_id;
7311 l_mol_qty := l_mol_rec.quantity;
7312 l_mol_prim_qty := l_mol_rec.primary_quantity;
7313 l_mol_qty2 := l_mol_rec.secondary_quantity;
7314 l_mol_uom_code2 := l_mol_rec.secondary_uom_code;
7315 l_mol_lpn_id := l_mol_rec.lpn_id;
7316 l_inventory_item_id := l_mol_rec.inventory_item_id;
7317 l_primary_uom_code := l_mol_rec.primary_uom_code;
7318 l_reservable_type := l_mol_rec.reservable_type;
7319 l_lot_control_code := l_mol_rec.lot_control_code;
7320 l_lot_divisible_flag := l_mol_rec.lot_divisible_flag;
7321 l_progress := '100';
7322
7323 -- For WIP supply MOL of type Flow or Work Order Less Completion,
7324 -- check to see if a specific OE demand has been associated to it.
7325 -- If so, we only want to attempt crossdocking to this demand.
7326 IF (l_wip_entity_type = 4) THEN
7327 -- Retrieve the OE demand info the WIP Flow job was completed for
7328 BEGIN
7329 SELECT DECODE(ool.source_document_type_id, 10, 8, 2),
7330 wlc.demand_source_header_id, wlc.demand_source_line
7331 INTO l_wip_demand_type_id, l_wip_demand_header_id, l_wip_demand_line_id
7332 FROM wip_lpn_completions wlc, oe_order_lines_all ool
7333 WHERE wlc.header_id = l_mol_rec.reference_id
7334 -- MOL reference_id is link to header_id in WIP LPN Flow Completions table
7335 AND wlc.wip_entity_id = l_supply_header_id
7336 AND wlc.lpn_id = l_mol_lpn_id
7337 AND wlc.inventory_item_id = l_inventory_item_id
7338 AND wlc.organization_id = l_organization_id
7339 AND wlc.demand_source_line = ool.line_id (+);
7340 EXCEPTION
7341 WHEN OTHERS THEN
7342 IF (l_debug = 1) THEN
7343 print_debug('1.1 - Exception retrieving demand that WIP job was completed for');
7344 END IF;
7345 GOTO end_crossdock;
7346 END;
7347
7348 -- See if WIP flow job was completed for a specific OE demand
7349 IF (l_wip_demand_header_id IS NOT NULL) THEN
7350 IF (l_debug = 1) THEN
7351 print_debug('1.1 - OE demand WIP job was completed for:');
7352 print_debug('1.1 - Demand Source Type: => ' || l_wip_demand_type_id);
7353 print_debug('1.1 - Demand Header ID: ===> ' || l_wip_demand_header_id);
7354 print_debug('1.1 - Demand Line ID: =====> ' || l_wip_demand_line_id);
7355 END IF;
7356 ELSE
7357 -- Null out the WIP demand type ID since it was defaulted to 2 in this case
7358 l_wip_demand_type_id := NULL;
7359 IF (l_debug = 1) THEN
7360 print_debug('1.1 - WIP job was not completed for a specific OE demand');
7361 END IF;
7362 END IF;
7363 END IF;
7364 l_progress := '105';
7365
7366 -- For WIP supply MOL of type Discrete, check that multiple distinct reservations
7367 -- against this WIP job do not exist. If so, do not crossdock this.
7368 -- Also if a single distinct reservation does exist, only crossdock peg against
7369 -- this specific demand if it is of type OE.
7370 IF (l_wip_entity_type = 1) THEN
7371 -- See how many reservations exist for the WIP Discrete job
7372 BEGIN
7373 OPEN existing_wip_rsvs;
7374 FETCH existing_wip_rsvs BULK COLLECT INTO l_existing_wip_rsvs_tb;
7375 CLOSE existing_wip_rsvs;
7376 EXCEPTION
7377 WHEN OTHERS THEN
7378 IF (l_debug = 1) THEN
7379 print_debug('1.1 - Exception retrieving the existing WIP reservations');
7380 END IF;
7381 GOTO end_crossdock;
7382 END;
7383 IF (l_debug = 1) THEN
7384 print_debug('1.1 - # of distinct existing reservations for WIP Discrete job: ' ||
7385 l_existing_wip_rsvs_tb.COUNT);
7386 END IF;
7387
7388 -- Do not crossdock if multiple reservations exist
7389 IF (l_existing_wip_rsvs_tb.COUNT > 1) THEN
7390 IF (l_debug = 1) THEN
7391 print_debug('1.1 - Multiple distinct reservations exist for WIP Discrete job');
7392 print_debug('1.1 - Do not crossdock WIP supply line');
7393 END IF;
7394 GOTO end_crossdock;
7395 END IF;
7396
7397 -- If a single distinct reservation exists for the WIP Discrete job as supply,
7398 -- retrieve the demand tied to it.
7399 IF (l_existing_wip_rsvs_tb.COUNT = 1) THEN
7400 -- Retrieve the demand info on the reservation
7401 l_rsv_index := l_existing_wip_rsvs_tb.FIRST;
7402 l_wip_demand_type_id := l_existing_wip_rsvs_tb(l_rsv_index).demand_source_type_id;
7403 l_wip_demand_header_id := l_existing_wip_rsvs_tb(l_rsv_index).demand_source_header_id;
7404 l_wip_demand_line_id := l_existing_wip_rsvs_tb(l_rsv_index).demand_source_line_id;
7405
7406 -- If the demand that the WIP Discrete job is tied to is NOT of type OE,
7407 -- skip all processing and do not crossdock.
7408 IF (l_wip_demand_type_id NOT IN (2, 8)) THEN
7409 IF (l_debug = 1) THEN
7410 print_debug('1.1 - WIP Discrete job is reserved to a non-OE demand');
7411 print_debug('1.1 - Do not crossdock WIP supply line');
7412 END IF;
7413 GOTO end_crossdock;
7414 END IF;
7415
7416 IF (l_debug = 1) THEN
7417 print_debug('1.1 - OE demand WIP job is reserved against:');
7418 print_debug('1.1 - Demand Source Type: => ' || l_wip_demand_type_id);
7419 print_debug('1.1 - Demand Header ID: ===> ' || l_wip_demand_header_id);
7420 print_debug('1.1 - Demand Line ID: =====> ' || l_wip_demand_line_id);
7421 END IF;
7422 END IF;
7423
7424 -- No existing reservations tied to the WIP job
7425 IF (l_existing_wip_rsvs_tb.COUNT = 0) THEN
7426 IF (l_debug = 1) THEN
7427 print_debug('1.1 - No demand is reserved against the WIP job');
7428 END IF;
7429 END IF;
7430
7431 END IF; -- END IF matches: IF (l_wip_entity_type = 1) THEN
7432 l_progress := '107';
7433
7434 -- Make sure the item is reservable.
7435 -- {{
7436 -- Non-reservable items should not be crossdocked. }}
7437 IF (l_reservable_type = 2) THEN
7438 IF (l_debug = 1) THEN
7439 print_debug('1.1 - Do not crossdock non-reservable items');
7440 END IF;
7441 GOTO end_crossdock;
7442 END IF;
7443 l_progress := '110';
7444
7445 -- Make sure the item is lot divisible if the item is lot controlled.
7446 -- {{
7447 -- Lot Indivisible items should not be crossdocked. }}
7448 IF (l_lot_control_code = 2 AND l_lot_divisible_flag = 'N') THEN
7449 IF (l_debug = 1) THEN
7450 print_debug('1.1 - Do not crossdock lot indivisible items');
7451 END IF;
7452 GOTO end_crossdock;
7453 END IF;
7454 l_progress := '120';
7455
7456 -- 1.2 - Lock the set of MOLs related to the inputted supply line.
7457 -- {{
7458 -- Test for errors while locking the set of supply MOLs related to the input MOL. }}
7459 BEGIN
7460 OPEN lock_mo_lines(p_lpn_context => l_mol_rec.lpn_context,
7461 p_wip_entity_id => l_mol_rec.txn_source_id,
7462 p_operation_seq_num => l_mol_rec.txn_source_line_id,
7463 p_repetitive_schedule_id => l_mol_rec.reference_id);
7464 FETCH lock_mo_lines BULK COLLECT INTO l_locked_mo_lines_tb;
7465 -- If no valid MO lines are found, do not error out.
7466 -- Skip to the end and do not crossdock the MOL.
7467 IF (l_locked_mo_lines_tb.COUNT = 0) THEN
7468 IF (l_debug = 1) THEN
7469 print_debug('1.2 - No valid Move Order supply lines found');
7470 END IF;
7471 CLOSE lock_mo_lines;
7472 GOTO end_crossdock;
7473 END IF;
7474 CLOSE lock_mo_lines;
7475 EXCEPTION
7476 WHEN OTHERS THEN
7477 IF (l_debug = 1) THEN
7478 print_debug('1.2 - Could not lock the Move Order supply lines');
7479 END IF;
7480 -- If we cannot lock the Move Order lines, do not error out.
7481 -- Skip to the end and do not crossdock the MOL.
7482 GOTO end_crossdock;
7483 END;
7484 IF (l_debug = 1) THEN
7485 print_debug('1.2 - Successfully locked the set of Move Order lines');
7486 END IF;
7487 l_progress := '130';
7488
7489 -- 1.3 - Calculate the crossdock window given the crossdock criteria time parameters.
7490
7491 -- Get the time interval values for the crossdock criteria.
7492 -- Time intervals will be defined using the function NUMTODSINTERVAL
7493 -- Crossdock Window Time Interval
7494 l_xdock_window_interval := NUMTODSINTERVAL
7495 (g_crossdock_criteria_tb(l_crossdock_criteria_id).window_interval,
7496 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_uom);
7497 IF (l_debug = 1) THEN
7498 print_debug('1.3 - Crossdock Window: ' ||
7499 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_interval || ' ' ||
7500 g_crossdock_criteria_tb(l_crossdock_criteria_id).window_uom);
7501 END IF;
7502 -- Buffer Time Interval
7503 -- The buffer time interval and UOM should either both be NULL or not NULL.
7504 l_buffer_interval := NUMTODSINTERVAL
7505 (NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_interval, 0),
7506 NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_uom, 'HOUR'));
7507 IF (l_debug = 1) THEN
7508 print_debug('1.3 - Buffer Time: ' ||
7509 g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_interval || ' ' ||
7510 g_crossdock_criteria_tb(l_crossdock_criteria_id).buffer_uom);
7511 END IF;
7512 -- Order Processing Time Interval
7513 -- The order processing time interval and UOM should either both be NULL or not NULL.
7514 l_processing_interval := NUMTODSINTERVAL
7515 (NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_interval, 0),
7516 NVL(g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_uom, 'HOUR'));
7517 IF (l_debug = 1) THEN
7518 print_debug('1.3 - Order Processing Time: ' ||
7519 g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_interval || ' ' ||
7520 g_crossdock_criteria_tb(l_crossdock_criteria_id).processing_uom);
7521 END IF;
7522
7523 -- Calculate the crossdock window start and end times
7524 l_xdock_start_time := SYSDATE + l_processing_interval + l_buffer_interval;
7525 l_xdock_end_time := SYSDATE + l_processing_interval + l_buffer_interval +
7526 l_xdock_window_interval;
7527 IF (l_debug = 1) THEN
7528 print_debug('1.3 - Crossdock start time: => ' ||
7529 TO_CHAR(l_xdock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
7530 print_debug('1.3 - Crossdock end time: ===> ' ||
7531 TO_CHAR(l_xdock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
7532 END IF;
7533 l_progress := '140';
7534
7535 -- Section 2: Crossdocking existing high level reservations
7536 -- For the inputted Move Order supply line, query to see if any existing high level
7537 -- reservations exist. If they do, we should try to detail those first.
7538 -- 2.1 - Query for and lock existing high level reservations for the MO supply line.
7539 -- - If a reservation cannot be locked, do not pick up the record for crossdocking.
7540 -- - Check that the UOM on the MOL supply and reservation match if UOM integrity is Yes.
7541 -- - For WIP MOL supply with existing reservations, calculate the WIP crossdocked qty.
7542 -- Get the total quantity for crossdocked MOLs from the same WIP job to the same demand.
7543 -- 2.2 - Query for and lock the available WDD demand line(s) with a released status of
7544 -- 'R' or 'B' tied to the order line on the reservation.
7545 -- - If cross project allocation is not allowed and the org is PJM enabled, make sure
7546 -- the project and task values on the MO supply line matches the demand.
7547 -- 2.3 - For each valid WDD demand, check that it is valid for crossdocking.
7548 -- - Demand source type must be allowed on the crossdock criteria.
7549 -- - Demand expected ship time must lie within the crossdock time window.
7550 -- 2.4 - Crossdock detail the reservation and update the demand and supply line records.
7551 -- 2.5 - If quantity still remains on the MOL to be crossdocked, see how much reservable
7552 -- quantity on the supply is actually available for crossdocking.
7553
7554 -- 2.1 - Query for and lock existing high level reservations for the MO supply line.
7555 -- - If a reservation cannot be locked, do not pick up the record for crossdocking.
7556 -- - Check that the UOM on the MOL supply and reservation match if UOM integrity is Yes.
7557 -- {{
7558 -- Test for MO supply lines with existing high level reservations.
7559 -- The possible demand source types for these reservations are:
7560 -- Sales Order (scheduled)
7561 -- Sales Order (backordered)
7562 -- Internal Order (scheduled)
7563 -- Internal Order (backordered) }}
7564 -- {{
7565 -- Test where an existing reservation is already locked. This record should not be
7566 -- picked up for crossdocking. }}
7567 -- {{
7568 -- Test for both OE and WIP MO supply lines with existing reservations. }}
7569 IF (l_debug = 1) THEN
7570 print_debug('2.1 - Query for existing high level reservations for the MO supply line');
7571 END IF;
7572 -- Initialize the table we are fetching records into.
7573 l_existing_rsvs_tb.DELETE;
7574 BEGIN
7575 OPEN existing_rsvs_cursor(p_lpn_context => l_mol_rec.lpn_context,
7576 p_wip_entity_id => l_mol_rec.txn_source_id);
7577 FETCH existing_rsvs_cursor BULK COLLECT INTO l_existing_rsvs_tb;
7578 CLOSE existing_rsvs_cursor;
7579 EXCEPTION
7580 WHEN OTHERS THEN
7581 IF (l_debug = 1) THEN
7582 print_debug('2.1 - Exception retrieving the existing reservations');
7583 END IF;
7584 GOTO after_existing_rsvs;
7585 --RAISE fnd_api.g_exc_unexpected_error;
7586 END;
7587 l_progress := '150';
7588
7589 -- Loop through the existing reservations and try to crossdock them
7590 l_rsv_index := l_existing_rsvs_tb.FIRST;
7591 LOOP
7592 -- If no existing reservations were found, exit out of loop.
7593 IF (l_existing_rsvs_tb.COUNT = 0) THEN
7594 IF (l_debug = 1) THEN
7595 print_debug('2.1 - No existing reservations to crossdock');
7596 END IF;
7597 EXIT;
7598 END IF;
7599
7600 -- Retrieve necessary parameters for the demand order line from the current reservation
7601 l_rsv_id := l_existing_rsvs_tb(l_rsv_index).reservation_id;
7602 l_rsv_qty := l_existing_rsvs_tb(l_rsv_index).reservation_quantity;
7603 l_rsv_uom_code := l_existing_rsvs_tb(l_rsv_index).reservation_uom_code;
7604 l_rsv_qty2 := l_existing_rsvs_tb(l_rsv_index).secondary_reservation_quantity;
7605 l_rsv_uom_code2 := l_existing_rsvs_tb(l_rsv_index).secondary_uom_code;
7606 l_rsv_prim_qty := l_existing_rsvs_tb(l_rsv_index).primary_reservation_quantity;
7607 l_rsv_prim_uom_code := l_existing_rsvs_tb(l_rsv_index).primary_uom_code;
7608 l_demand_type_id := l_existing_rsvs_tb(l_rsv_index).demand_source_type_id;
7609 l_demand_so_header_id := l_existing_rsvs_tb(l_rsv_index).demand_source_header_id;
7610 l_demand_line_id := l_existing_rsvs_tb(l_rsv_index).demand_source_line_id;
7611
7612 -- Get the demand OE header ID from the Sales Order header ID
7613 inv_salesorder.get_oeheader_for_salesorder
7614 (p_salesorder_id => l_demand_so_header_id,
7615 x_oe_header_id => l_demand_header_id,
7616 x_return_status => x_return_status);
7617
7618 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7619 IF (l_debug = 1) THEN
7620 print_debug('2.1 - Error returned from get_oeheader_for_salesorder API: '
7621 || x_return_status);
7622 END IF;
7623 GOTO next_reservation;
7624 END IF;
7625
7626 IF (l_debug = 1) THEN
7627 print_debug('2.1 - Reservation ID: ========> ' || l_rsv_id);
7628 print_debug('2.1 - Reservation Quantity: ==> ' || l_rsv_qty || ' ' ||
7629 l_rsv_uom_code);
7630 print_debug('2.1 - Reservation Quantity2: => ' || l_rsv_qty2 || ' ' ||
7631 l_rsv_uom_code2);
7632 print_debug('2.1 - Reservation Prim Qty: ==> ' || l_rsv_prim_qty || ' ' ||
7633 l_rsv_prim_uom_code);
7634 print_debug('2.1 - Demand source type ID: => ' || l_demand_type_id);
7635 print_debug('2.1 - Demand SO header ID: ===> ' || l_demand_so_header_id);
7636 print_debug('2.1 - Demand header ID: ======> ' || l_demand_header_id);
7637 print_debug('2.1 - Demand line ID: ========> ' || l_demand_line_id);
7638 END IF;
7639 l_progress := '160';
7640
7641 -- Make sure the primary UOM code on the reservation matches the one for the item.
7642 -- This error condition should not come about but if it does, just skip this
7643 -- reservation and go to the next one.
7644 IF (l_primary_uom_code <> l_rsv_prim_uom_code) THEN
7645 IF (l_debug = 1) THEN
7646 print_debug('2.1 - Item and reservation primary UOM codes do not match!');
7647 END IF;
7648 GOTO next_reservation;
7649 END IF;
7650
7651 -- Check that the UOM on the MOL supply and reservation match if UOM integrity is Yes.
7652 -- {{
7653 -- Test for a crossdock criteria where UOM Integrity is Yes and the existing reservation
7654 -- has a different UOM from the MOL supply lines. }}
7655 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1 AND
7656 l_rsv_uom_code <> l_supply_uom_code) THEN
7657 IF (l_debug = 1) THEN
7658 print_debug('2.1 - RSV and MOL UOM codes do not match and UOM Integrity is Yes!');
7659 END IF;
7660 GOTO next_reservation;
7661 END IF;
7662 l_progress := '170';
7663
7664 -- - For WIP MOL supply with existing reservations, calculate the WIP crossdocked qty.
7665 -- Get the total quantity for crossdocked MOLs from the same WIP job to the same demand.
7666 -- {{
7667 -- Test for WIP MOL supply line where another MOL from the same WIP job is already
7668 -- satisfying part of an existing reservation. That quantity should be decremented
7669 -- from the reservation when deciding on how much quantity to detail. }}
7670 IF (l_supply_type_id = 5) THEN
7671 -- Retrieve the Primary qty for other WIP MOLs for the same WIP job that have
7672 -- already been pegged to this existing reservation.
7673 IF (l_debug = 1) THEN
7674 print_debug('2.1 - Retrieve the WIP crossdocked qty');
7675 END IF;
7676 BEGIN
7677 OPEN get_wip_xdock_qty(p_wip_entity_id => l_mol_rec.txn_source_id,
7678 p_operation_seq_num => l_mol_rec.txn_source_line_id,
7679 p_repetitive_schedule_id => l_mol_rec.reference_id,
7680 p_demand_source_header_id => l_demand_header_id,
7681 p_demand_source_line_id => l_demand_line_id);
7682 FETCH get_wip_xdock_qty INTO l_wip_xdock_prim_qty;
7683 IF (get_wip_xdock_qty%NOTFOUND) THEN
7684 l_wip_xdock_prim_qty := 0;
7685 END IF;
7686 CLOSE get_wip_xdock_qty;
7687 EXCEPTION
7688 WHEN OTHERS THEN
7689 IF (l_debug = 1) THEN
7690 print_debug('2.1 - Exception retrieving the WIP crossdocked qty');
7691 END IF;
7692 GOTO after_existing_rsvs;
7693 END;
7694 IF (l_debug = 1) THEN
7695 print_debug('2.1 - WIP crossdocked qty: ' || l_wip_xdock_prim_qty || ' '
7696 || l_primary_uom_code);
7697 END IF;
7698
7699 -- Decrement the reservation quantity to be crossdocked if part of it
7700 -- is already satisfied by existing crossdocked WIP MOLs.
7701 IF (l_wip_xdock_prim_qty <> 0) THEN
7702 -- Decrement the RSV qty
7703 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
7704 l_primary_uom_code, l_rsv_uom_code);
7705 IF (l_conversion_rate < 0) THEN
7706 IF (l_debug = 1) THEN
7707 print_debug('2.1 - Error while obtaining UOM conversion rate for RSV qty');
7708 END IF;
7709 GOTO next_reservation;
7710 END IF;
7711 -- Round the converted quantity to the standard precision
7712 l_wip_xdock_qty := ROUND(l_conversion_rate * l_wip_xdock_prim_qty, l_conversion_precision);
7713 l_rsv_qty := l_rsv_qty - l_wip_xdock_qty;
7714 IF (l_debug = 1) THEN
7715 print_debug('2.1 - Adjusted RSV Qty: ======> ' || l_rsv_qty || ' ' ||
7716 l_rsv_uom_code);
7717 END IF;
7718
7719 -- If the reservation has no quantity left on it to be satisfied,
7720 -- skip to the next available reservation.
7721 IF (l_rsv_qty = 0) THEN
7722 GOTO next_reservation;
7723 END IF;
7724
7725 -- Decrement the RSV qty2
7726 IF (l_rsv_uom_code2 IS NOT NULL) THEN
7727 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
7728 l_primary_uom_code, l_rsv_uom_code2);
7729 IF (l_conversion_rate < 0) THEN
7730 IF (l_debug = 1) THEN
7731 print_debug('2.1 - Error while obtaining UOM conversion rate for RSV qty2');
7732 END IF;
7733 GOTO next_reservation;
7734 END IF;
7735 -- Round the converted quantity to the standard precision
7736 l_wip_xdock_qty2 := ROUND(l_conversion_rate * l_wip_xdock_prim_qty, l_conversion_precision);
7737 l_rsv_qty2 := l_rsv_qty2 - l_wip_xdock_qty2;
7738 IF (l_debug = 1) THEN
7739 print_debug('2.1 - Adjusted RSV Qty2: =====> ' || l_rsv_qty2 || ' ' ||
7740 l_rsv_uom_code2);
7741 END IF;
7742 END IF;
7743
7744 -- Decrement the RSV primary qty
7745 l_rsv_prim_qty := l_rsv_prim_qty - l_wip_xdock_prim_qty;
7746 IF (l_debug = 1) THEN
7747 print_debug('2.1 - Adjusted RSV Prim Qty: => ' || l_rsv_prim_qty || ' ' ||
7748 l_rsv_prim_uom_code);
7749 END IF;
7750 END IF; -- End IF matches: IF (l_wip_xdock_prim_qty <> 0) THEN
7751 END IF; -- End Calculating WIP crossdocked qty
7752 l_progress := '175';
7753
7754 -- 2.2 - Query for and lock the available WDD demand line(s) with a released status of
7755 -- 'R' or 'B' tied to the order line on the reservation.
7756 -- - If cross project allocation is not allowed and the org is PJM enabled, make sure
7757 -- the project and task values on the MO supply line matches the demand.
7758
7759 -- Initialize the table we are fetching records into.
7760 l_reserved_wdd_lines_tb.DELETE;
7761 BEGIN
7762 OPEN reserved_wdd_lines(l_mol_rec.project_id, l_mol_rec.task_id);
7763 FETCH reserved_wdd_lines BULK COLLECT INTO l_reserved_wdd_lines_tb;
7764 CLOSE reserved_wdd_lines;
7765 EXCEPTION
7766 WHEN OTHERS THEN
7767 IF (l_debug = 1) THEN
7768 print_debug('2.2 - Exception retrieving the reserved WDD demand lines');
7769 END IF;
7770 GOTO next_reservation;
7771 --RAISE fnd_api.g_exc_unexpected_error;
7772 END;
7773 l_progress := '180';
7774
7775 -- Loop through the available WDD lines and try to crossdock the valid ones
7776 l_wdd_index := l_reserved_wdd_lines_tb.FIRST;
7777 LOOP
7778 -- Define a savepoint so if an exception occurs while updating database records such
7779 -- as WDD, RSV, or MOL, we need to rollback the changes and goto the next reserved
7780 -- WDD demand line to crossdock (if one exists).
7781 SAVEPOINT Reserved_WDD_sp;
7782
7783 -- Initialize the variable below used for updating crossdocked WDD records,
7784 -- in case we need to rollback the changes to local PLSQL data structures.
7785 l_xdocked_wdd_index := NULL;
7786
7787 -- If no valid reserved WDD lines were found, exit out of loop.
7788 -- This should not happen if the reservation was allowed to be created.
7789 IF (l_reserved_wdd_lines_tb.COUNT = 0) THEN
7790 IF (l_debug = 1) THEN
7791 print_debug('2.2 - No valid reserved WDD lines to crossdock');
7792 END IF;
7793 EXIT;
7794 END IF;
7795
7796 -- Retrieve necessary parameters for the demand order line from the current reservation
7797 l_demand_line_detail_id := l_reserved_wdd_lines_tb(l_wdd_index).delivery_detail_id;
7798 l_demand_qty := l_reserved_wdd_lines_tb(l_wdd_index).requested_quantity;
7799 l_demand_uom_code := l_reserved_wdd_lines_tb(l_wdd_index).requested_quantity_uom;
7800 l_demand_qty2 := l_reserved_wdd_lines_tb(l_wdd_index).requested_quantity2;
7801 l_demand_uom_code2 := l_reserved_wdd_lines_tb(l_wdd_index).requested_quantity_uom2;
7802 l_demand_status := l_reserved_wdd_lines_tb(l_wdd_index).released_status;
7803 l_demand_project_id := l_reserved_wdd_lines_tb(l_wdd_index).project_id;
7804 l_demand_task_id := l_reserved_wdd_lines_tb(l_wdd_index).task_id;
7805 -- Set the WIP variables to NULL since the demand line is an OE WDD demand
7806 l_wip_entity_id := NULL;
7807 l_operation_seq_num := NULL;
7808 l_repetitive_schedule_id := NULL;
7809 l_wip_supply_type := NULL;
7810
7811 IF (l_debug = 1) THEN
7812 print_debug('2.2 - Current reserved WDD line to check for crossdock:');
7813 print_debug('2.2 - Demand line detail ID: ==> ' || l_demand_line_detail_id);
7814 print_debug('2.2 - Demand line qty: ========> ' || l_demand_qty || ' ' ||
7815 l_demand_uom_code);
7816 print_debug('2.2 - Demand line qty2: =======> ' || l_demand_qty2 || ' ' ||
7817 l_demand_uom_code2);
7818 print_debug('2.2 - Demand Released Status: => ' || l_demand_status);
7819 print_debug('2.2 - Demand Project ID: ======> ' || l_demand_project_id);
7820 print_debug('2.2 - Demand Task ID: =========> ' || l_demand_task_id);
7821 END IF;
7822
7823 -- 2.3 - For each valid WDD demand, check that it is valid for crossdocking.
7824 -- - Demand source type must be allowed on the crossdock criteria.
7825 -- - Demand expected ship time must lie within the crossdock time window.
7826 IF (l_debug = 1) THEN
7827 print_debug('2.3 - Check if the current reserved WDD line is valid for crossdocking');
7828 END IF;
7829
7830 -- Set the appropriate Opportunistic Crossdock demand source code. This uses a different
7831 -- set of lookup values compared to the reservations demand source codes.
7832 IF (l_demand_type_id = 2 AND l_demand_status = 'R') THEN
7833 -- Sales Order (Scheduled)
7834 l_demand_src_code := G_OPP_DEM_SO_SCHED;
7835 ELSIF (l_demand_type_id = 2 AND l_demand_status = 'B') THEN
7836 -- Sales Order (Backordered)
7837 l_demand_src_code := G_OPP_DEM_SO_BKORD;
7838 ELSIF (l_demand_type_id = 8 AND l_demand_status = 'R') THEN
7839 -- Internal Order (Scheduled)
7840 l_demand_src_code := G_OPP_DEM_IO_SCHED;
7841 ELSIF (l_demand_type_id = 8 AND l_demand_status = 'B') THEN
7842 -- Internal Order (Backordered)
7843 l_demand_src_code := G_OPP_DEM_IO_BKORD;
7844 ELSE
7845 -- Invalid demand for crossdocking.
7846 -- {{
7847 -- For prior existing reservations that are not supported for crossdocking (WIP),
7848 -- make sure we do not try to crossdock them. }}
7849 GOTO next_reserved_wdd;
7850 END IF;
7851 IF (l_debug = 1) THEN
7852 print_debug('2.3 - Crossdock Demand Source Code: => ' || l_demand_src_code);
7853 END IF;
7854 l_progress := '190';
7855
7856 -- Demand source type must be allowed on the crossdock criteria.
7857 -- Check if the demand line tied to the reservation is valid for crossdocking
7858 -- based on the valid demand types allowed for the crossdock criteria.
7859 -- {{
7860 -- Test for existing reservations for valid demand types to crossdock which are
7861 -- not allowed on the crossdock criteria. Processing should stop and the next
7862 -- reserved WDD demand should be considered for crossdocking. }}
7863 IF (NOT WMS_XDOCK_UTILS_PVT.Is_Eligible_Demand_Source
7864 (p_criterion_id => l_crossdock_criteria_id,
7865 p_source_code => l_demand_src_code)) THEN
7866 -- Demand line on reservation is not valid source for crossdocking
7867 IF (l_debug = 1) THEN
7868 print_debug('2.3 - WDD Demand line on reservation is not a valid source');
7869 END IF;
7870 GOTO next_reserved_wdd;
7871 END IF;
7872 l_progress := '200';
7873
7874 -- Demand expected ship time must lie within the crossdock time window.
7875 -- Check if the demand line tied to the reservation is valid for crossdocking
7876 -- based on the crossdock window for the crossdock criteria.
7877 IF (l_debug = 1) THEN
7878 print_debug('2.3 - Determine the expected ship time for the demand line');
7879 END IF;
7880 Get_Expected_Time
7881 (p_source_type_id => l_demand_type_id,
7882 p_source_header_id => l_demand_so_header_id,
7883 p_source_line_id => l_demand_line_id,
7884 p_source_line_detail_id => l_demand_line_detail_id,
7885 p_supply_or_demand => G_SRC_TYPE_DEM,
7886 p_crossdock_criterion_id => l_crossdock_criteria_id,
7887 x_return_status => x_return_status,
7888 x_msg_count => x_msg_count,
7889 x_msg_data => x_msg_data,
7890 x_dock_start_time => l_dock_start_time,
7891 x_dock_mean_time => l_dock_mean_time,
7892 x_dock_end_time => l_dock_end_time,
7893 x_expected_time => l_demand_expected_time);
7894
7895 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
7896 IF (l_debug = 1) THEN
7897 print_debug('2.3 - Success returned from Get_Expected_Time API');
7898 END IF;
7899 ELSE
7900 IF (l_debug = 1) THEN
7901 print_debug('2.3 - Failure returned from Get_Expected_Time API');
7902 END IF;
7903 GOTO next_reserved_wdd;
7904 --RAISE fnd_api.g_exc_error;
7905 END IF;
7906
7907 -- Do not crossdock the demand line on the reservation if an expected ship
7908 -- time cannot be determined.
7909 -- {{
7910 -- If an expected ship time for the demand line on an existing reservation
7911 -- cannot be determined, skip processing and move on to the next reserved WDD
7912 -- demand. }}
7913 IF (l_demand_expected_time IS NULL) THEN
7914 IF (l_debug = 1) THEN
7915 print_debug('2.3 - Unable to crossdock reservation since demand expected time is NULL');
7916 END IF;
7917 GOTO next_reserved_wdd;
7918 END IF;
7919 IF (l_debug = 1) THEN
7920 print_debug('2.3 - Demand expected time: => ' ||
7921 TO_CHAR(l_demand_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
7922 END IF;
7923 l_progress := '210';
7924
7925 -- See if the WDD demand line lies within the crossdock time window.
7926 -- If a dock appointment for the demand does not exist and the crossdock criteria
7927 -- allows rescheduling of the demand for anytime on the expected ship date, set the
7928 -- appropriate logic to determine if the demand is valid.
7929 -- Demands with an expected ship time in the past are considered as ready to ship out
7930 -- immediately. Thus they are all valid for Opportunistic Crossdocking.
7931 -- {{
7932 -- Test for a demand line on an existing reservation that does not have a dock appointment
7933 -- and demand reschedule is allowed. }}
7934 -- {{
7935 -- Test for a demand line on an existing reservation lying within the crossdock window. }}
7936 -- {{
7937 -- Test for a demand line on an existing reservation not lying within the crossdock
7938 -- window. In this case, we cannot crossdock the existing reservation so just move
7939 -- on to the next reserved WDD. }}
7940 IF ((l_dock_start_time IS NULL AND
7941 g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_demand_reschedule_flag = 1 AND
7942 l_demand_expected_time BETWEEN TRUNC(l_xdock_start_time) AND
7943 TO_DATE(TO_CHAR(TRUNC(l_xdock_end_time), 'DD-MON-YYYY') ||
7944 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS'))
7945 OR (l_demand_expected_time < SYSDATE)
7946 OR (l_demand_expected_time BETWEEN l_xdock_start_time AND l_xdock_end_time)) THEN
7947 -- Demand is valid for crossdocking based on crossdock time window
7948 IF (l_debug = 1) THEN
7949 print_debug('2.3 - Demand line is within the crossdock window');
7950 END IF;
7951 ELSE
7952 -- Demand is not valid for crossdocking so skip to the next
7953 -- reserved WDD demand to crossdock
7954 IF (l_debug = 1) THEN
7955 print_debug('2.3 - Demand line is not within the crossdock window');
7956 END IF;
7957 GOTO next_reserved_wdd;
7958 END IF;
7959 l_progress := '220';
7960
7961 -- 2.4 - Crossdock detail the reservation and update the demand and supply line records.
7962 IF (l_debug = 1) THEN
7963 print_debug('2.4 - Crossdock detail the relevant records: RSV, WDD, MOL');
7964 END IF;
7965
7966 -- Convert the WDD qty to the UOM on the supply line.
7967 -- Retrieve the conversion rate for the item/from UOM/to UOM combination.
7968 -- {{
7969 -- Test that the WDD quantity is converted properly to the UOM on the supply line. }}
7970 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
7971 l_demand_uom_code, l_supply_uom_code);
7972 IF (l_conversion_rate < 0) THEN
7973 IF (l_debug = 1) THEN
7974 print_debug('2.4 - Error while obtaining UOM conversion rate for WDD qty');
7975 END IF;
7976 -- Rollback any db changes that might have occurred (currently none).
7977 ROLLBACK TO Reserved_WDD_sp;
7978 -- Process the next existing reserved WDD.
7979 GOTO next_reserved_wdd;
7980 END IF;
7981 -- Round the converted quantity to the standard precision
7982 l_wdd_txn_qty := ROUND(l_conversion_rate * l_demand_qty, l_conversion_precision);
7983 IF (l_debug = 1) THEN
7984 print_debug('2.4 - WDD qty: =====> ' || l_demand_qty || ' ' || l_demand_uom_code);
7985 print_debug('2.4 - WDD txn qty: => ' || l_wdd_txn_qty || ' ' || l_supply_uom_code);
7986 END IF;
7987 l_progress := '230';
7988
7989 -- Convert the RSV qty to the UOM on the supply line.
7990 -- Retrieve the conversion rate for the item/from UOM/to UOM combination.
7991 -- {{
7992 -- Test that the RSV quantity is converted properly to the UOM on the supply line. }}
7993 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
7994 l_rsv_uom_code, l_supply_uom_code);
7995 IF (l_conversion_rate < 0) THEN
7996 IF (l_debug = 1) THEN
7997 print_debug('2.4 - Error while obtaining UOM conversion rate for RSV qty');
7998 END IF;
7999 -- Rollback any db changes that might have occurred (currently none).
8000 ROLLBACK TO Reserved_WDD_sp;
8001 -- Process the next existing reserved WDD.
8002 GOTO next_reserved_wdd;
8003 END IF;
8004 -- Round the converted quantity to the standard precision
8005 l_rsv_txn_qty := ROUND(l_conversion_rate * l_rsv_qty, l_conversion_precision);
8006 IF (l_debug = 1) THEN
8007 print_debug('2.4 - RSV qty: =====> ' || l_rsv_qty || ' ' || l_rsv_uom_code);
8008 print_debug('2.4 - RSV txn qty: => ' || l_rsv_txn_qty || ' ' || l_supply_uom_code);
8009 END IF;
8010 l_progress := '240';
8011
8012 -- Calculate the Available to Detail quantity.
8013 -- {{
8014 -- Test that the available to detail quantity is calculated properly,
8015 -- i.e. is lower than WDD, RSV, and MOL qty, and is an integer value if
8016 -- UOM integrity = 'Y'. }}
8017 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1) THEN
8018 -- UOM Integrity is 'Yes'
8019 l_atd_qty := LEAST(FLOOR(l_wdd_txn_qty), FLOOR(l_rsv_txn_qty), FLOOR(l_mol_qty));
8020 ELSE
8021 -- UOM Integrity is 'No'
8022 l_atd_qty := LEAST(l_wdd_txn_qty, l_rsv_txn_qty, l_mol_qty);
8023 END IF;
8024 IF (l_debug = 1) THEN
8025 print_debug('2.4 - Available to detail qty: ' || l_atd_qty || ' ' ||
8026 l_supply_uom_code);
8027 END IF;
8028 -- If the ATD qty is 0, then goto the next reserved WDD to crossdock.
8029 -- This is possible if the UOM integrity flag is 'Y' and the resultant quantities
8030 -- were floored to 0.
8031 -- {{
8032 -- Test for ATD qty = 0. This can come about if UOM integrity is Yes and the
8033 -- demand, reservation or supply line gets floored to 0. }}
8034 IF (l_atd_qty = 0) THEN
8035 IF (l_debug = 1) THEN
8036 print_debug('2.4 - No available qty to detail for this WDD/RSV/MOL combination');
8037 END IF;
8038 -- Rollback any db changes that might have occurred (currently none).
8039 ROLLBACK TO Reserved_WDD_sp;
8040 -- Process the next existing reserved WDD.
8041 GOTO next_reserved_wdd;
8042 END IF;
8043 l_progress := '250';
8044
8045 -- Convert l_atd_qty to the primary UOM
8046 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
8047 l_supply_uom_code, l_primary_uom_code);
8048 IF (l_conversion_rate < 0) THEN
8049 IF (l_debug = 1) THEN
8050 print_debug('2.4 - Error while obtaining primary UOM conversion rate for ATD qty');
8051 END IF;
8052 -- Rollback any db changes that might have occurred (currently none).
8053 ROLLBACK TO Reserved_WDD_sp;
8054 -- Process the next existing reserved WDD.
8055 GOTO next_reserved_wdd;
8056 END IF;
8057 -- Round the converted quantity to the standard precision
8058 l_atd_prim_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
8059 IF (l_debug = 1) THEN
8060 print_debug('2.4 - ATD qty in primary UOM: => ' || l_atd_prim_qty || ' ' ||
8061 l_primary_uom_code);
8062 END IF;
8063 l_progress := '260';
8064
8065 -- Crossdock the WDD record, splitting it if necessary.
8066 IF (l_debug = 1) THEN
8067 print_debug('2.4 - Call the Crossdock_WDD API to crossdock/split the WDD');
8068 END IF;
8069 Crossdock_WDD
8070 (p_log_prefix => '2.4 - ',
8071 p_crossdock_type => G_CRT_TYPE_OPP,
8072 p_batch_id => l_batch_id,
8073 p_wsh_release_table => l_wsh_release_table,
8074 p_trolin_delivery_ids => l_trolin_delivery_ids,
8075 p_del_detail_id => l_del_detail_id,
8076 l_wdd_index => l_dummy_wdd_index,
8077 l_debug => l_debug,
8078 l_inventory_item_id => l_inventory_item_id,
8079 l_wdd_txn_qty => l_wdd_txn_qty,
8080 l_atd_qty => l_atd_qty,
8081 l_atd_wdd_qty => l_atd_wdd_qty,
8082 l_atd_wdd_qty2 => l_atd_wdd_qty2,
8083 l_supply_uom_code => l_supply_uom_code,
8084 l_demand_uom_code => l_demand_uom_code,
8085 l_demand_uom_code2 => l_demand_uom_code2,
8086 l_conversion_rate => l_conversion_rate,
8087 l_conversion_precision => l_conversion_precision,
8088 l_demand_line_detail_id => l_demand_line_detail_id,
8089 l_index => l_index,
8090 l_detail_id_tab => l_detail_id_tab,
8091 l_action_prms => l_action_prms,
8092 l_action_out_rec => l_action_out_rec,
8093 l_split_wdd_id => l_split_wdd_id,
8094 l_detail_info_tab => l_detail_info_tab,
8095 l_in_rec => l_in_rec,
8096 l_out_rec => l_out_rec,
8097 l_mol_line_id => l_mol_line_id,
8098 l_split_wdd_index => l_split_wdd_index,
8099 l_split_delivery_index => l_split_delivery_index,
8100 l_split_wdd_rel_rec => l_split_wdd_rel_rec,
8101 l_allocation_method => l_allocation_method,
8102 l_demand_qty => l_demand_qty,
8103 l_demand_qty2 => l_demand_qty2,
8104 l_demand_atr_qty => l_demand_atr_qty,
8105 l_xdocked_wdd_index => l_xdocked_wdd_index,
8106 l_supply_type_id => l_supply_type_id,
8107 x_return_status => x_return_status,
8108 x_msg_count => x_msg_count,
8109 x_msg_data => x_msg_data,
8110 x_error_code => l_error_code
8111 );
8112
8113 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8114 IF (l_debug = 1) THEN
8115 print_debug('2.4 - Error returned from Crossdock_WDD API: '
8116 || x_return_status);
8117 END IF;
8118 --RAISE fnd_api.g_exc_error;
8119 -- If an exception occurs while modifying a database record, rollback the changes
8120 -- and just go to the next WDD record or reservation to crossdock.
8121 ROLLBACK TO Reserved_WDD_sp;
8122 -- We need to also rollback changes done to local PLSQL data structures
8123 IF (l_xdocked_wdd_index IS NOT NULL) THEN
8124 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
8125 END IF;
8126 -- Process the next existing reserved WDD.
8127 GOTO next_reserved_wdd;
8128 ELSE
8129 IF (l_debug = 1) THEN
8130 print_debug('2.4 - Successfully crossdocked/split the WDD record');
8131 END IF;
8132 END IF;
8133 l_progress := '270';
8134
8135
8136 -- Crossdock the RSV record, splitting it if necessary.
8137 -- Do not modify the reservation if supply is of type WIP.
8138 IF (l_debug = 1) THEN
8139 print_debug('2.4 - Call the Crossdock_RSV API to crossdock/split the RSV');
8140 END IF;
8141 Crossdock_RSV
8142 (p_log_prefix => '2.4 - ',
8143 p_crossdock_type => G_CRT_TYPE_OPP,
8144 l_debug => l_debug,
8145 l_inventory_item_id => l_inventory_item_id,
8146 l_rsv_txn_qty => l_rsv_txn_qty,
8147 l_atd_qty => l_atd_qty,
8148 l_atd_rsv_qty => l_atd_rsv_qty,
8149 l_atd_rsv_qty2 => l_atd_rsv_qty2,
8150 l_atd_prim_qty => l_atd_prim_qty,
8151 l_supply_uom_code => l_supply_uom_code,
8152 l_rsv_uom_code => l_rsv_uom_code,
8153 l_rsv_uom_code2 => l_rsv_uom_code2,
8154 l_primary_uom_code => l_primary_uom_code,
8155 l_conversion_rate => l_conversion_rate,
8156 l_conversion_precision => l_conversion_precision,
8157 l_original_rsv_rec => l_original_rsv_rec,
8158 l_rsv_id => l_rsv_id,
8159 l_to_rsv_rec => l_to_rsv_rec,
8160 l_split_wdd_id => l_split_wdd_id,
8161 l_crossdock_criteria_id => l_crossdock_criteria_id,
8162 l_demand_expected_time => l_demand_expected_time,
8163 l_supply_expected_time => l_supply_expected_time,
8164 l_original_serial_number => l_original_serial_number,
8165 l_split_rsv_id => l_split_rsv_id,
8166 l_rsv_qty => l_rsv_qty,
8167 l_rsv_qty2 => l_rsv_qty2,
8168 l_to_serial_number => l_to_serial_number,
8169 l_supply_type_id => l_supply_type_id,
8170 x_return_status => x_return_status,
8171 x_msg_count => x_msg_count,
8172 x_msg_data => x_msg_data,
8173 x_error_code => l_error_code
8174 );
8175
8176 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8177 IF (l_debug = 1) THEN
8178 print_debug('2.4 - Error returned from Crossdock_RSV API: '
8179 || x_return_status);
8180 END IF;
8181 --RAISE fnd_api.g_exc_error;
8182 -- If an exception occurs while modifying a database record, rollback the changes
8183 -- and just go to the next WDD record or reservation to crossdock.
8184 ROLLBACK TO Reserved_WDD_sp;
8185 -- We need to also rollback changes done to local PLSQL data structures
8186 IF (l_xdocked_wdd_index IS NOT NULL) THEN
8187 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
8188 END IF;
8189 -- Process the next existing reserved WDD.
8190 GOTO next_reserved_wdd;
8191 ELSE
8192 IF (l_debug = 1) THEN
8193 print_debug('2.4 - Successfully crossdocked/split the RSV record');
8194 END IF;
8195 END IF;
8196 l_progress := '280';
8197
8198
8199 -- Crossdock the MOL record, splitting it if necessary
8200 IF (l_debug = 1) THEN
8201 print_debug('2.4 - Call the Crossdock_MOL API to crossdock/split the MOL');
8202 END IF;
8203 Crossdock_MOL
8204 (p_log_prefix => '2.4 - ',
8205 p_crossdock_type => G_CRT_TYPE_OPP,
8206 l_debug => l_debug,
8207 l_inventory_item_id => l_inventory_item_id,
8208 l_mol_qty => l_mol_qty,
8209 l_mol_qty2 => l_mol_qty2,
8210 l_atd_qty => l_atd_qty,
8211 l_atd_mol_qty2 => l_atd_mol_qty2,
8212 l_supply_uom_code => l_supply_uom_code,
8213 l_mol_uom_code2 => l_mol_uom_code2,
8214 l_conversion_rate => l_conversion_rate,
8215 l_conversion_precision => l_conversion_precision,
8216 l_mol_prim_qty => l_mol_prim_qty,
8217 l_atd_prim_qty => l_atd_prim_qty,
8218 l_split_wdd_id => l_split_wdd_id,
8219 l_mol_header_id => l_mol_header_id,
8220 l_mol_line_id => l_mol_line_id,
8221 l_supply_atr_qty => l_supply_atr_qty,
8222 l_demand_type_id => l_demand_type_id,
8223 l_wip_entity_id => l_wip_entity_id,
8224 l_operation_seq_num => l_operation_seq_num,
8225 l_repetitive_schedule_id => l_repetitive_schedule_id,
8226 l_wip_supply_type => l_wip_supply_type,
8227 l_xdocked_wdd_index => l_xdocked_wdd_index,
8228 l_detail_info_tab => l_detail_info_tab,
8229 l_wdd_index => l_dummy_wdd_index,
8230 l_split_wdd_index => l_split_wdd_index,
8231 p_wsh_release_table => l_wsh_release_table,
8232 l_supply_type_id => l_supply_type_id,
8233 x_return_status => x_return_status,
8234 x_msg_count => x_msg_count,
8235 x_msg_data => x_msg_data,
8236 x_error_code => l_error_code,
8237 x_new_mol_id => l_new_mol_id, --9695544
8238 l_criterion_type => G_CRT_TYPE_OPP
8239 );
8240
8241 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8242 IF (l_debug = 1) THEN
8243 print_debug('2.4 - Error returned from Crossdock_MOL API: '
8244 || x_return_status);
8245 END IF;
8246 --RAISE fnd_api.g_exc_error;
8247 -- If an exception occurs while modifying a database record, rollback the changes
8248 -- and just go to the next WDD record or reservation to crossdock.
8249 ROLLBACK TO Reserved_WDD_sp;
8250 -- We need to also rollback changes done to local PLSQL data structures
8251 IF (l_xdocked_wdd_index IS NOT NULL) THEN
8252 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
8253 END IF;
8254 -- Process the next existing reserved WDD.
8255 GOTO next_reserved_wdd;
8256 ELSE
8257 IF (l_debug = 1) THEN
8258 print_debug('2.4 - Successfully crossdocked/split the MOL record');
8259 END IF;
8260 END IF;
8261 l_progress := '290';
8262
8263 IF ( NVL(l_new_mol_id,0) > 0 ) THEN
8264 --9695544-Add this MOL and xdock criteria in global pl/sq table
8265 WMS_Cross_Dock_Pvt.insert_xdock_criteria( l_new_mol_id,l_crossdock_criteria_id,x_return_status,x_msg_data,x_msg_count);
8266 END IF;
8267 -- Exit out of loop if the MOL supply has been fully crossdocked or the
8268 -- reservation has been fully consumed.
8269 IF (l_mol_qty = 0 OR l_rsv_qty = 0) THEN
8270 EXIT;
8271 END IF;
8272
8273 <<next_reserved_wdd>>
8274 EXIT WHEN l_wdd_index = l_reserved_wdd_lines_tb.LAST;
8275 l_wdd_index := l_reserved_wdd_lines_tb.NEXT(l_wdd_index);
8276 END LOOP; -- End looping through WDD lines in l_existing_rsvs_tb
8277
8278 -- Exit out of existing reservations loop if the MOL supply has been fully crossdocked.
8279 -- There is no need to consider anymore existing reservations.
8280 IF (l_mol_qty = 0) THEN
8281 EXIT;
8282 END IF;
8283
8284 <<next_reservation>>
8285 EXIT WHEN l_rsv_index = l_existing_rsvs_tb.LAST;
8286 l_rsv_index := l_existing_rsvs_tb.NEXT(l_rsv_index);
8287 END LOOP; -- End looping through existing reservations
8288 l_progress := '300';
8289
8290 <<after_existing_rsvs>>
8291 IF (l_debug = 1) THEN
8292 print_debug('2.5 - Finished processing existing reservations');
8293 print_debug('2.5 - Quantity left on MOL: ' || l_mol_qty || ' ' || l_supply_uom_code);
8294 END IF;
8295
8296 -- 2.5 - If quantity still remains on the MOL to be crossdocked, see how much reservable
8297 -- quantity on the supply is actually available for crossdocking.
8298 -- {{
8299 -- Test for a supply MOL being fully crossdocked by existing reservations.
8300 -- Further crossdock processing should not occur. }}
8301 IF (l_mol_qty = 0) THEN
8302 GOTO end_crossdock;
8303 END IF;
8304
8305 IF (l_debug = 1) THEN
8306 print_debug('2.5 - Calculate the ATR qty on the MOL supply line for crossdocking');
8307 END IF;
8308 -- {{
8309 -- Test getting the available to reserve quantity for the MOL supply for
8310 -- type RCV as well as WIP. }}
8311 IF (l_supply_type_id = 27) THEN
8312 -- RCV MOL
8313 INV_RESERVATION_AVAIL_PVT.Available_supply_to_reserve
8314 (p_api_version_number => 1.0,
8315 p_init_msg_lst => fnd_api.g_false,
8316 x_return_status => x_return_status,
8317 x_msg_count => x_msg_count,
8318 x_msg_data => x_msg_data,
8319 p_organization_id => l_organization_id,
8320 p_item_id => l_inventory_item_id,
8321 p_supply_source_type_id => l_supply_type_id,
8322 p_supply_source_header_id => l_supply_header_id,
8323 p_supply_source_line_id => l_supply_line_id,
8324 p_supply_source_line_detail => l_supply_line_detail_id,
8325 p_project_id => l_mol_rec.project_id,
8326 p_task_id => l_mol_rec.task_id,
8327 x_qty_available_to_reserve => l_supply_atr_prim_qty,
8328 x_qty_available => l_supply_available_qty);
8329 ELSIF (l_wip_entity_type = 1) THEN
8330 -- WIP Discrete Job MOL
8331 INV_RESERVATION_AVAIL_PVT.Available_supply_to_reserve
8332 (p_api_version_number => 1.0,
8333 p_init_msg_lst => fnd_api.g_false,
8334 x_return_status => x_return_status,
8335 x_msg_count => x_msg_count,
8336 x_msg_data => x_msg_data,
8337 p_organization_id => l_organization_id,
8338 p_item_id => l_inventory_item_id,
8339 p_supply_source_type_id => l_supply_type_id,
8340 p_supply_source_header_id => l_supply_header_id,
8341 p_supply_source_line_id => l_supply_line_id,
8342 p_supply_source_line_detail => l_supply_line_detail_id,
8343 p_project_id => l_mol_rec.project_id,
8344 p_task_id => l_mol_rec.task_id,
8345 x_qty_available_to_reserve => l_supply_atr_prim_qty,
8346 x_qty_available => l_supply_available_qty);
8347 ELSE -- l_wip_entity_type = 4
8348 -- WIP Flow Job MOL
8349 -- The full quantity on the MOL is available for crossdocking since
8350 -- you cannot create reservations against WIP Flow jobs as supply in R12.
8351 l_supply_atr_prim_qty := l_mol_prim_qty;
8352 END IF;
8353
8354 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8355 IF (l_debug = 1) THEN
8356 print_debug('2.5 - Error returned from available_supply_to_reserve API: '
8357 || x_return_status);
8358 END IF;
8359 GOTO end_crossdock;
8360 --RAISE fnd_api.g_exc_error;
8361 END IF;
8362
8363 -- The ATR qty returned is for all of receiving. Since we are working on a specific
8364 -- MOL supply line, we need to use a LEAST to get the min qty value.
8365 -- If the MOL is for WIP, the ATR qty is for all of the lines for the same WIP job.
8366 l_supply_atr_prim_qty := LEAST(l_mol_prim_qty, l_supply_atr_prim_qty);
8367
8368 IF (l_debug = 1) THEN
8369 print_debug('2.5 - Available qty to reserve (primary) for supply: ' ||
8370 l_supply_atr_prim_qty || ' ' || l_primary_uom_code);
8371 END IF;
8372 l_progress := '360';
8373
8374 -- Check how much quantity is available to be crossdocked.
8375 -- {{
8376 -- Test for case where the MOL supply, after considering existing reservations, does not
8377 -- have any reservable quantity. This line cannot be crossdocked and we should end
8378 -- crossdocking logic. }}
8379 IF (l_supply_atr_prim_qty <= 0) THEN
8380 GOTO end_crossdock;
8381 ELSE
8382 -- Convert the ATR primary quantity to the UOM on the MOL supply line
8383 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
8384 l_primary_uom_code, l_supply_uom_code);
8385 IF (l_conversion_rate < 0) THEN
8386 IF (l_debug = 1) THEN
8387 print_debug('2.5 - Error while obtaining Primary UOM conversion rate for WDD');
8388 END IF;
8389 GOTO end_crossdock;
8390 END IF;
8391 -- Round the converted quantity to the standard precision
8392 l_supply_atr_qty := ROUND(l_conversion_rate * l_supply_atr_prim_qty, l_conversion_precision);
8393 IF (l_debug = 1) THEN
8394 print_debug('2.5 - Available qty to reserve for supply: ' || l_supply_atr_qty ||
8395 ' ' || l_supply_uom_code);
8396 END IF;
8397 l_progress := '370';
8398
8399 -- Instead of splitting the MOL record here with the ATR quantity, just keep track
8400 -- of that qty and use it later on when determining the available to detail qty.
8401 -- In this way, we can minimize the amount of MOL splitting, doing it only when
8402 -- absolutely necessary.
8403 END IF;
8404
8405 -- Section 3: Build the set of available demand lines for the MOL supply
8406 -- 3.1 - For each available demand source type for the crossdock criteria,
8407 -- retrieve the available demand lines.
8408 -- 3.2 - For each demand line retrieved, determine the expected ship time.
8409 -- If the demand line does not lie within the crossdock window, remove it
8410 -- from the local PLSQL tables prior to insertion into the global temp table.
8411 -- 3.3 - Insert the available crossdockable demand lines into the global temp table.
8412 -- 3.4 - Retrieve all of the demand lines inserted into the global temp table and
8413 -- store it in the shopping basket table. If prioritize documents, order this
8414 -- by the source type.
8415 -- 3.5 - Sort the demand lines in the shopping basket table based on the crossdocking
8416 -- goals.
8417
8418 -- 3.1 - For each available demand source type for the crossdock criteria,
8419 -- retrieve the available demand lines.
8420 -- {{
8421 -- Test for different demand source types for opportunistic crossdocking. Make sure
8422 -- only the valid ones are retrieved, i.e. SO, IO (both scheduled and backordered) and
8423 -- WIP backordered component demands. }}
8424 IF (l_debug = 1) THEN
8425 print_debug('3.1 - Query and cache the available demand source types for crossdocking');
8426 END IF;
8427 BEGIN
8428 OPEN demand_src_types_cursor;
8429 FETCH demand_src_types_cursor BULK COLLECT INTO l_demand_src_types_tb;
8430 CLOSE demand_src_types_cursor;
8431 EXCEPTION
8432 WHEN OTHERS THEN
8433 IF (l_debug = 1) THEN
8434 print_debug('3.1 - Exception retrieving the eligible demand source types');
8435 END IF;
8436 GOTO end_crossdock;
8437 END;
8438 IF (l_debug = 1) THEN
8439 print_debug('3.1 - Successfully retrieved ' || l_demand_src_types_tb.COUNT ||
8440 ' eligible demand source types');
8441 END IF;
8442
8443 -- Set a savepoint in case an error occurs while inserting demand line records
8444 -- into the global temp table.
8445 SAVEPOINT Demand_Lines_sp;
8446
8447 FOR i IN 1 .. l_demand_src_types_tb.COUNT LOOP
8448 -- Store the current demand source code
8449 l_demand_src_code := l_demand_src_types_tb(i);
8450
8451 -- Retrieve the available demand lines for the current demand source type,
8452 -- item,org, project and task.
8453 IF (l_debug = 1) THEN
8454 IF (l_demand_src_code = G_OPP_DEM_SO_SCHED) THEN
8455 print_debug('3.1 - Demand source type to retrieve: Scheduled Sales Order');
8456 ELSIF (l_demand_src_code = G_OPP_DEM_SO_BKORD) THEN
8457 print_debug('3.1 - Demand source type to retrieve: Backordered Sales Order');
8458 ELSIF (l_demand_src_code = G_OPP_DEM_IO_SCHED) THEN
8459 print_debug('3.1 - Demand source type to retrieve: Scheduled Internal Order');
8460 ELSIF (l_demand_src_code = G_OPP_DEM_IO_BKORD) THEN
8461 print_debug('3.1 - Demand source type to retrieve: Backordered Internal Order');
8462 ELSIF (l_demand_src_code = G_OPP_DEM_WIP_BKORD) THEN
8463 print_debug('3.1 - Demand source type to retrieve: Backordered WIP Component');
8464 ELSE
8465 print_debug('3.1 - Demand source type to retrieve: INVALID DEMAND!');
8466 END IF;
8467 END IF;
8468
8469 -- Initialize the tables we are BULK fetching into
8470 l_header_id_tb.DELETE;
8471 l_line_id_tb.DELETE;
8472 l_line_detail_id_tb.DELETE;
8473 l_dock_start_time_tb.DELETE;
8474 l_dock_mean_time_tb.DELETE;
8475 l_dock_end_time_tb.DELETE;
8476 l_expected_time_tb.DELETE;
8477 l_quantity_tb.DELETE;
8478 l_uom_code_tb.DELETE;
8479 l_secondary_quantity_tb.DELETE;
8480 l_secondary_uom_code_tb.DELETE;
8481 l_project_id_tb.DELETE;
8482 l_task_id_tb.DELETE;
8483 l_wip_supply_type_tb.DELETE;
8484
8485 -- Bulk collect the demand line cursors into the PLSQL tables based on
8486 -- the current crossdock demand source type.
8487 -- {{
8488 -- Make sure that if cross project/task allocation is not allowed, only valid demand
8489 -- lines that match the project/task on the supply are retrieved. }}
8490 IF (l_demand_src_code = G_OPP_DEM_SO_SCHED) THEN
8491 -- Sales Order (Scheduled)
8492 BEGIN
8493 OPEN SO_scheduled_lines(l_mol_rec.project_id, l_mol_rec.task_id);
8494 FETCH SO_scheduled_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
8495 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb,
8496 l_secondary_quantity_tb, l_secondary_uom_code_tb, l_project_id_tb, l_task_id_tb,
8497 l_wip_supply_type_tb;
8498 CLOSE SO_scheduled_lines;
8499 EXCEPTION
8500 WHEN OTHERS THEN
8501 IF (l_debug = 1) THEN
8502 print_debug('3.1 - Could not retrieve the Scheduled SO demand lines');
8503 END IF;
8504 -- If we cannot retrieve the available demand lines, do not error out.
8505 -- Rollback any db changes that might have occurred (currently none).
8506 ROLLBACK TO Demand_Lines_sp;
8507 GOTO end_crossdock;
8508 END;
8509 l_demand_type_id := 2;
8510 ELSIF (l_demand_src_code = G_OPP_DEM_SO_BKORD) THEN
8511 -- Sales Order (Backordered)
8512 BEGIN
8513 OPEN SO_backordered_lines(l_mol_rec.project_id, l_mol_rec.task_id);
8514 FETCH SO_backordered_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
8515 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb,
8516 l_secondary_quantity_tb, l_secondary_uom_code_tb, l_project_id_tb, l_task_id_tb,
8517 l_wip_supply_type_tb;
8518 CLOSE SO_backordered_lines;
8519 EXCEPTION
8520 WHEN OTHERS THEN
8521 IF (l_debug = 1) THEN
8522 print_debug('3.1 - Could not retrieve the Backordered SO demand lines');
8523 END IF;
8524 -- If we cannot retrieve the available demand lines, do not error out.
8525 -- Rollback any db changes that might have occurred (currently none).
8526 ROLLBACK TO Demand_Lines_sp;
8527 GOTO end_crossdock;
8528 END;
8529 l_demand_type_id := 2;
8530 ELSIF (l_demand_src_code = G_OPP_DEM_IO_SCHED) THEN
8531 -- Internal Order (Scheduled)
8532 BEGIN
8533 OPEN IO_scheduled_lines(l_mol_rec.project_id, l_mol_rec.task_id);
8534 FETCH IO_scheduled_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
8535 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb,
8536 l_secondary_quantity_tb, l_secondary_uom_code_tb, l_project_id_tb, l_task_id_tb,
8537 l_wip_supply_type_tb;
8538 CLOSE IO_scheduled_lines;
8539 EXCEPTION
8540 WHEN OTHERS THEN
8541 IF (l_debug = 1) THEN
8542 print_debug('3.1 - Could not retrieve the Scheduled IO demand lines');
8543 END IF;
8544 -- If we cannot retrieve the available demand lines, do not error out.
8545 -- Rollback any db changes that might have occurred (currently none).
8546 ROLLBACK TO Demand_Lines_sp;
8547 GOTO end_crossdock;
8548 END;
8549 l_demand_type_id := 8;
8550 ELSIF (l_demand_src_code = G_OPP_DEM_IO_BKORD) THEN
8551 -- Internal Order (Backordered)
8552 BEGIN
8553 OPEN IO_backordered_lines(l_mol_rec.project_id, l_mol_rec.task_id);
8554 FETCH IO_backordered_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
8555 l_line_detail_id_tb, l_quantity_tb, l_uom_code_tb,
8556 l_secondary_quantity_tb, l_secondary_uom_code_tb, l_project_id_tb, l_task_id_tb,
8557 l_wip_supply_type_tb;
8558 CLOSE IO_backordered_lines;
8559 EXCEPTION
8560 WHEN OTHERS THEN
8561 IF (l_debug = 1) THEN
8562 print_debug('3.1 - Could not retrieve the Backordered IO demand lines');
8563 END IF;
8564 -- If we cannot retrieve the available demand lines, do not error out.
8565 -- Rollback any db changes that might have occurred (currently none).
8566 ROLLBACK TO Demand_Lines_sp;
8567 GOTO end_crossdock;
8568 END;
8569 l_demand_type_id := 8;
8570 ELSIF (l_demand_src_code = G_OPP_DEM_WIP_BKORD) THEN
8571 -- WIP backordered component
8572 BEGIN
8573 OPEN wip_component_demand_lines(l_mol_rec.project_id, l_mol_rec.task_id,
8574 l_xdock_start_time, l_xdock_end_time);
8575 FETCH wip_component_demand_lines BULK COLLECT INTO l_header_id_tb, l_line_id_tb,
8576 l_line_detail_id_tb, l_expected_time_tb, l_quantity_tb, l_uom_code_tb,
8577 l_secondary_quantity_tb, l_secondary_uom_code_tb, l_project_id_tb, l_task_id_tb,
8578 l_wip_supply_type_tb;
8579 CLOSE wip_component_demand_lines;
8580 EXCEPTION
8581 WHEN OTHERS THEN
8582 IF (l_debug = 1) THEN
8583 print_debug('3.1 - Could not retrieve the WIP component demand lines');
8584 END IF;
8585 -- If we cannot retrieve the available demand lines, do not error out.
8586 -- Rollback any db changes that might have occurred (currently none).
8587 ROLLBACK TO Demand_Lines_sp;
8588 GOTO end_crossdock;
8589 END;
8590 l_demand_type_id := 5;
8591 ELSE
8592 -- Invalid demand type for crossdocking
8593 -- Rollback any db changes that might have occurred (currently none).
8594 ROLLBACK TO Demand_Lines_sp;
8595 GOTO end_crossdock;
8596 END IF; -- End retrieving demand lines for different demand source types
8597 IF (l_debug = 1) THEN
8598 IF (l_demand_src_code = G_OPP_DEM_SO_SCHED) THEN
8599 print_debug('3.1 - Successfully retrieved ' || l_header_id_tb.COUNT ||
8600 ' available line(s) for Scheduled Sales Order');
8601 ELSIF (l_demand_src_code = G_OPP_DEM_SO_BKORD) THEN
8602 print_debug('3.1 - Successfully retrieved ' || l_header_id_tb.COUNT ||
8603 ' available line(s) for Backordered Sales Order');
8604 ELSIF (l_demand_src_code = G_OPP_DEM_IO_SCHED) THEN
8605 print_debug('3.1 - Successfully retrieved ' || l_header_id_tb.COUNT ||
8606 ' available line(s) for Scheduled Internal Order');
8607 ELSIF (l_demand_src_code = G_OPP_DEM_IO_BKORD) THEN
8608 print_debug('3.1 - Successfully retrieved ' || l_header_id_tb.COUNT ||
8609 ' available line(s) for Backordered Internal Order');
8610 ELSIF (l_demand_src_code = G_OPP_DEM_WIP_BKORD) THEN
8611 print_debug('3.1 - Successfully retrieved ' || l_header_id_tb.COUNT ||
8612 ' available line(s) for Backordered WIP Component');
8613 END IF;
8614 END IF;
8615 l_progress := '380';
8616
8617 -- 3.2 - For each demand line retrieved, determine the expected ship time.
8618 -- If the demand line does not lie within the crossdock window, remove it
8619 -- from the local PLSQL tables prior to insertion into the global temp table.
8620 -- {{
8621 -- Make sure that demand lines with an expected time that lies outside of the crossdock
8622 -- window are removed from the PLSQL tables and not inserted into the global temp table. }}
8623 IF (l_debug = 1) THEN
8624 print_debug('3.2 - For each demand line retrieved, calculate the expected ship time');
8625 END IF;
8626 FOR j IN 1 .. l_header_id_tb.COUNT LOOP
8627 -- Call the Get_Expected_Time API for OE demand. WIP demand will already
8628 -- have the date_required value retrieved.
8629 IF (l_demand_type_id <> 5) THEN
8630 Get_Expected_Time
8631 (p_source_type_id => l_demand_type_id,
8632 p_source_header_id => l_header_id_tb(j),
8633 p_source_line_id => l_line_id_tb(j),
8634 p_source_line_detail_id => l_line_detail_id_tb(j),
8635 p_supply_or_demand => G_SRC_TYPE_DEM,
8636 p_crossdock_criterion_id => l_crossdock_criteria_id,
8637 x_return_status => x_return_status,
8638 x_msg_count => x_msg_count,
8639 x_msg_data => x_msg_data,
8640 x_dock_start_time => l_dock_start_time_tb(j),
8641 x_dock_mean_time => l_dock_mean_time_tb(j),
8642 x_dock_end_time => l_dock_end_time_tb(j),
8643 x_expected_time => l_expected_time_tb(j));
8644
8645 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
8646 IF (l_debug = 1) THEN
8647 print_debug('3.2 - Success returned from Get_Expected_Time API');
8648 END IF;
8649 ELSE
8650 IF (l_debug = 1) THEN
8651 print_debug('3.2 - Failure returned from Get_Expected_Time API');
8652 END IF;
8653 -- Rollback any db changes that might have occurred (currently none).
8654 ROLLBACK TO Demand_Lines_sp;
8655 GOTO end_crossdock;
8656 END IF;
8657 ELSE
8658 -- WIP demand line. Use the value retrieved in the l_expected_time_tb
8659 -- and populate the same value for the dock appointment tables.
8660 l_dock_start_time_tb(j) := l_expected_time_tb(j);
8661 l_dock_mean_time_tb(j) := l_expected_time_tb(j);
8662 l_dock_end_time_tb(j) := l_expected_time_tb(j);
8663 END IF;
8664
8665 -- Check if the current demand line lies within the crossdock window.
8666 -- Remove any demand lines that are not crossdockable from the PLSQL tables.
8667 -- Do this only for non-WIP demand types. WIP demand lines retrieved will already
8668 -- be checked to lie within the crossdock window. This logic is done within the
8669 -- wip_component_demand_lines cursor.
8670 -- Demand lines with an expected ship time in the past are always eligible for
8671 -- opportunistic crossdocking.
8672 IF (l_debug = 1) THEN
8673 print_debug('g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_demand_reschedule_flag:'||
8674 g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_demand_reschedule_flag);
8675 print_debug('l_xdock_start_time'||l_xdock_start_time);
8676 print_debug('l_xdock_end_time'||l_xdock_end_time);
8677 print_debug('l_expected_time_tb(j) '||l_expected_time_tb(j) );
8678 END IF;
8679
8680 IF (l_demand_type_id <> 5) THEN
8681 IF (l_expected_time_tb(j) IS NOT NULL AND
8682 ((l_dock_start_time_tb(j) IS NULL AND
8683 g_crossdock_criteria_tb(l_crossdock_criteria_id).allow_demand_reschedule_flag = 1 AND
8684 l_expected_time_tb(j) BETWEEN TRUNC(l_xdock_start_time) AND
8685 TO_DATE(TO_CHAR(TRUNC(l_xdock_end_time), 'DD-MON-YYYY') ||
8686 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS'))
8687 OR (l_expected_time_tb(j) < SYSDATE)
8688 OR (l_expected_time_tb(j) BETWEEN l_xdock_start_time AND l_xdock_end_time))) THEN
8689 -- Demand is within the crossdock window
8690 IF (l_debug = 1) THEN
8691 print_debug('3.2 - Current demand line is valid for crossdocking');
8692 END IF;
8693 ELSE
8694 -- Demand is not valid for crossdocking based on crossdock time window
8695 -- so remove this line from the local tables prior to insertion.
8696 IF (l_debug = 1) THEN
8697 print_debug('3.2 - Current demand line is invalid for crossdocking so remove it');
8698 END IF;
8699 l_header_id_tb.DELETE(j);
8700 l_line_id_tb.DELETE(j);
8701 l_line_detail_id_tb.DELETE(j);
8702 l_quantity_tb.DELETE(j);
8703 l_uom_code_tb.DELETE(j);
8704 l_secondary_quantity_tb.DELETE(j);
8705 l_secondary_uom_code_tb.DELETE(j);
8706 l_project_id_tb.DELETE(j);
8707 l_task_id_tb.DELETE(j);
8708 l_dock_start_time_tb.DELETE(j);
8709 l_dock_mean_time_tb.DELETE(j);
8710 l_dock_end_time_tb.DELETE(j);
8711 l_expected_time_tb.DELETE(j);
8712 l_wip_supply_type_tb.DELETE(j);
8713 END IF;
8714 END IF;
8715
8716 -- If we do not allow partial WIP crossdock, check if the demand is already tied
8717 -- to a WIP supply. If yes, then only WIP supply lines are valid for crossdocking.
8718 -- Similarly, if the supply is a WIP supply, check that the demand is not already tied
8719 -- to non-WIP and non-Inventory supplies.
8720 -- Do this check only for non-WIP demand lines since those are the ones that will have
8721 -- reservations created for the crossdock. Only do this check if the demand line has not
8722 -- already been removed above for not lying within the crossdock window.
8723 IF (l_header_id_tb.EXISTS(j) AND l_demand_type_id <> 5) THEN
8724 IF (WMS_XDOCK_CUSTOM_APIS_PUB.g_allow_partial_wip_xdock = 'N') THEN
8725 IF ((l_supply_type_id <> 5 AND WMS_XDOCK_PEGGING_PUB.is_demand_tied_to_wip
8726 (p_organization_id => l_organization_id,
8727 p_inventory_item_id => l_inventory_item_id,
8728 p_demand_type_id => l_demand_type_id,
8729 p_demand_header_id => l_header_id_tb(j),
8730 p_demand_line_id => l_line_id_tb(j)) = 'Y') OR
8731 (l_supply_type_id = 5 AND WMS_XDOCK_PEGGING_PUB.is_demand_tied_to_non_wip
8732 (p_organization_id => l_organization_id,
8733 p_inventory_item_id => l_inventory_item_id,
8734 p_demand_type_id => l_demand_type_id,
8735 p_demand_header_id => l_header_id_tb(j),
8736 p_demand_line_id => l_line_id_tb(j)) = 'Y')) THEN
8737 IF (l_debug = 1) THEN
8738 print_debug('3.2 - Demand cannot be crossdocked, partial WIP xdock is not allowed');
8739 END IF;
8740 l_header_id_tb.DELETE(j);
8741 l_line_id_tb.DELETE(j);
8742 l_line_detail_id_tb.DELETE(j);
8743 l_quantity_tb.DELETE(j);
8744 l_uom_code_tb.DELETE(j);
8745 l_secondary_quantity_tb.DELETE(j);
8746 l_secondary_uom_code_tb.DELETE(j);
8747 l_project_id_tb.DELETE(j);
8748 l_task_id_tb.DELETE(j);
8749 l_dock_start_time_tb.DELETE(j);
8750 l_dock_mean_time_tb.DELETE(j);
8751 l_dock_end_time_tb.DELETE(j);
8752 l_expected_time_tb.DELETE(j);
8753 l_wip_supply_type_tb.DELETE(j);
8754 END IF;
8755 END IF;
8756 END IF;
8757
8758 -- If the supply MOL is WIP, then there could be a specific OE demand that we
8759 -- can ONLY crossdock to. If that is the case, do not insert any other demand lines
8760 -- into the xdock pegging temp table. Only do this check if the demand line has not
8761 -- already been removed above for not lying within the crossdock window or being part
8762 -- of a partial WIP xdock.
8763 /*9695544-Now we allow WIP LPN to xdock against multiple SO lines . So commenting the following out
8764 IF (l_header_id_tb.EXISTS(j) AND
8765 l_wip_entity_type IS NOT NULL AND l_wip_demand_header_id IS NOT NULL) THEN
8766 IF (l_demand_type_id <> l_wip_demand_type_id OR
8767 l_header_id_tb(j) <> l_wip_demand_header_id OR
8768 l_line_id_tb(j) <> l_wip_demand_line_id) THEN
8769 -- Demand is not valid for crossdocking due to WIP specified OE demand restriction.
8770 -- So remove this line from the local tables prior to insertion.
8771 IF (l_debug = 1) THEN
8772 print_debug('3.2 - Current demand line does not match WIP OE demand so remove it');
8773 END IF;
8774 l_header_id_tb.DELETE(j);
8775 l_line_id_tb.DELETE(j);
8776 l_line_detail_id_tb.DELETE(j);
8777 l_quantity_tb.DELETE(j);
8778 l_uom_code_tb.DELETE(j);
8779 l_secondary_quantity_tb.DELETE(j);
8780 l_secondary_uom_code_tb.DELETE(j);
8781 l_project_id_tb.DELETE(j);
8782 l_task_id_tb.DELETE(j);
8783 l_dock_start_time_tb.DELETE(j);
8784 l_dock_mean_time_tb.DELETE(j);
8785 l_dock_end_time_tb.DELETE(j);
8786 l_expected_time_tb.DELETE(j);
8787 l_wip_supply_type_tb.DELETE(j);
8788 END IF;
8789 END IF;
8790 */
8791 END LOOP; -- End looping through demand lines retrieved
8792 IF (l_debug = 1) THEN
8793 print_debug('3.2 - Finished calculating expected time for all demand lines');
8794 END IF;
8795 l_progress := '390';
8796
8797 -- 3.3 - Insert the available crossdockable demand lines into the global temp table.
8798 -- {{
8799 -- Make sure the valid crossdockable demand lines are properly inserted into the
8800 -- global temp table. }}
8801 IF (l_debug = 1) THEN
8802 print_debug('3.3 - Insert ' || l_header_id_tb.COUNT ||
8803 ' crossdockable demand lines into the global temp table');
8804 END IF;
8805 BEGIN
8806 FORALL k IN INDICES OF l_header_id_tb
8807 INSERT INTO wms_xdock_pegging_gtmp
8808 (inventory_item_id,
8809 xdock_source_code,
8810 source_type_id,
8811 source_header_id,
8812 source_line_id,
8813 source_line_detail_id,
8814 dock_start_time,
8815 dock_mean_time,
8816 dock_end_time,
8817 expected_time,
8818 quantity,
8819 uom_code,
8820 secondary_quantity,
8821 secondary_uom_code,
8822 project_id,
8823 task_id,
8824 wip_supply_type
8825 )
8826 VALUES
8827 (l_inventory_item_id,
8828 l_demand_src_code,
8829 l_demand_type_id,
8830 l_header_id_tb(k),
8831 l_line_id_tb(k),
8832 l_line_detail_id_tb(k),
8833 l_dock_start_time_tb(k),
8834 l_dock_mean_time_tb(k),
8835 l_dock_end_time_tb(k),
8836 l_expected_time_tb(k),
8837 l_quantity_tb(k),
8838 l_uom_code_tb(k),
8839 l_secondary_quantity_tb(k),
8840 l_secondary_uom_code_tb(k),
8841 l_project_id_tb(k),
8842 l_task_id_tb(k),
8843 l_wip_supply_type_tb(k)
8844 );
8845 EXCEPTION
8846 WHEN OTHERS THEN
8847 IF (l_debug = 1) THEN
8848 print_debug('3.3 - Error inserting available demand lines into temp table');
8849 END IF;
8850 -- If an exception occurs while inserting demand line records,
8851 -- rollback the changes and stop crossdock processing.
8852 ROLLBACK TO Demand_Lines_sp;
8853 GOTO end_crossdock;
8854 END;
8855 IF (l_debug = 1) THEN
8856 print_debug('3.3 - Successfully inserted ' || l_header_id_tb.COUNT ||
8857 ' crossdockable demand lines into temp table');
8858 END IF;
8859 l_progress := '400';
8860
8861 -- Clear the PLSQL tables used once the data is inserted into the global temp table
8862 IF (l_header_id_tb.COUNT > 0) THEN
8863 l_header_id_tb.DELETE;
8864 l_line_id_tb.DELETE;
8865 l_line_detail_id_tb.DELETE;
8866 l_dock_start_time_tb.DELETE;
8867 l_dock_mean_time_tb.DELETE;
8868 l_dock_end_time_tb.DELETE;
8869 l_expected_time_tb.DELETE;
8870 l_quantity_tb.DELETE;
8871 l_uom_code_tb.DELETE;
8872 l_secondary_quantity_tb.DELETE;
8873 l_secondary_uom_code_tb.DELETE;
8874 l_project_id_tb.DELETE;
8875 l_task_id_tb.DELETE;
8876 l_wip_supply_type_tb.DELETE;
8877 END IF;
8878 l_progress := '410';
8879
8880 END LOOP; -- End looping through eligible demand source types
8881
8882 -- 3.4 - Retrieve all of the demand lines inserted into the global temp table and
8883 -- store it in the shopping basket table. If prioritize documents, order this
8884 -- by the source type.
8885 -- {{
8886 -- Make sure the demand lines retrieved are sorted in order of document priority if
8887 -- necessary. }}
8888 IF (l_debug = 1) THEN
8889 print_debug('3.4 - Retrieve all of the demand lines that are valid for crossdocking');
8890 END IF;
8891
8892 -- Iniitialize the shopping basket table which will store the valid supply lines
8893 -- for crossdocking to the current demand line.
8894 l_shopping_basket_tb.DELETE;
8895
8896 -- Initialize the demand document priority variables
8897 l_so_sched_priority := 99;
8898 l_so_back_priority := 99;
8899 l_io_sched_priority := 99;
8900 l_io_back_priority := 99;
8901 l_wip_priority := 99;
8902
8903 -- Get the valid demand source types to retrieve.
8904 -- The demand source types are cached in the order of the document priority already.
8905 -- Just use the same index value for the document priority variable.
8906 -- Do this only if we need to prioritize documents for the crossdock criteria
8907 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).prioritize_documents_flag = 1) THEN
8908 FOR i IN 1 .. l_demand_src_types_tb.COUNT LOOP
8909 IF (l_demand_src_types_tb(i) = G_OPP_DEM_SO_SCHED) THEN
8910 l_so_sched_priority := i;
8911 ELSIF (l_demand_src_types_tb(i) = G_OPP_DEM_SO_BKORD) THEN
8912 l_so_back_priority := i;
8913 ELSIF (l_demand_src_types_tb(i) = G_OPP_DEM_IO_SCHED) THEN
8914 l_io_sched_priority := i;
8915 ELSIF (l_demand_src_types_tb(i) = G_OPP_DEM_IO_BKORD) THEN
8916 l_io_back_priority := i;
8917 ELSIF (l_demand_src_types_tb(i) = G_OPP_DEM_WIP_BKORD) THEN
8918 l_wip_priority := i;
8919 END IF;
8920 END LOOP;
8921 END IF;
8922
8923 -- Now get the valid demand lines for crossdocking and store it in the
8924 -- shopping basket table. All of the demand lines stored in the global temp table
8925 -- should already match the project/task of the supply (if necessary). They should
8926 -- also lie within the crossdock window. We are just sorting them basically here.
8927 -- {{
8928 -- Make sure the demand lines are retrieved properly into the shopping basket table.
8929 -- Do this both with and without enforcing document priority. Also use various
8930 -- available demand types. }}
8931 BEGIN
8932 OPEN get_demand_lines
8933 (p_crossdock_goal => g_crossdock_criteria_tb(l_crossdock_criteria_id).crossdock_goal,
8934 p_so_sched_priority => l_so_sched_priority,
8935 p_so_back_priority => l_so_back_priority,
8936 p_io_sched_priority => l_io_sched_priority,
8937 p_io_back_priority => l_io_back_priority,
8938 p_wip_priority => l_wip_priority);
8939 FETCH get_demand_lines BULK COLLECT INTO l_shopping_basket_tb;
8940 CLOSE get_demand_lines;
8941 EXCEPTION
8942 WHEN OTHERS THEN
8943 IF (l_debug = 1) THEN
8944 print_debug('3.4 - Could not retrieve the valid demand lines for available demand types');
8945 END IF;
8946 -- If we cannot retrieve the valid demand lines, do not error out.
8947 -- Stop crossdock processing and exit out of the API.
8948 GOTO end_crossdock;
8949 END;
8950 IF (l_debug = 1) THEN
8951 print_debug('3.4 - Successfully populated the shopping basket table with ' ||
8952 l_shopping_basket_tb.COUNT || ' crossdockable demand lines');
8953 END IF;
8954 l_progress := '420';
8955
8956 -- 3.5 - Sort the demand lines in the shopping basket table based on the crossdocking
8957 -- goals.
8958 -- For crossdock goals of Minimize Wait and Maximize Crossdock, the demand lines in the
8959 -- shopping basket have already been sorted.
8960 -- {{
8961 -- Test out the custom crossdock goal method of sorting the shopping basket lines.
8962 -- The not implemented stub version should just pass back the inputted shopping basket
8963 -- table without sorting them. }}
8964 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).crossdock_goal = G_CUSTOM_GOAL) THEN
8965 -- For each record in the shopping basket table, call the available to reserve API
8966 -- to determine how much quantity from each demand line is available for crossdocking.
8967 -- We need to do this since the custom logic might decide which demand lines to consume
8968 -- based on the reservable quantity (e.g. Best Fit SPQ type of logic).
8969 IF (l_debug = 1) THEN
8970 print_debug('3.5 - Use custom logic to sort the demand lines');
8971 END IF;
8972
8973 FOR i IN 1 .. l_shopping_basket_tb.COUNT LOOP
8974
8975 -- Call the Available_demand_to_reserve API for OE demand.
8976 -- The quantity_backordered on the WIP demand is the same as
8977 -- the ATR qty so it is fully reserveable.
8978 IF (l_shopping_basket_tb(i).source_type_id <> 5) THEN
8979 IF (l_debug = 1) THEN
8980 print_debug('3.5 - Call the Available_demand_to_reserve API');
8981 END IF;
8982 INV_RESERVATION_AVAIL_PVT.Available_demand_to_reserve
8983 (p_api_version_number => 1.0,
8984 p_init_msg_lst => fnd_api.g_false,
8985 x_return_status => x_return_status,
8986 x_msg_count => x_msg_count,
8987 x_msg_data => x_msg_data,
8988 p_primary_uom_code => l_primary_uom_code,
8989 p_demand_source_type_id => l_shopping_basket_tb(i).source_type_id,
8990 p_demand_source_header_id => l_shopping_basket_tb(i).source_header_id,
8991 p_demand_source_line_id => l_shopping_basket_tb(i).source_line_id,
8992 p_demand_source_line_detail => l_shopping_basket_tb(i).source_line_detail_id,
8993 p_project_id => l_shopping_basket_tb(i).project_id,
8994 p_task_id => l_shopping_basket_tb(i).task_id,
8995 x_qty_available_to_reserve => l_demand_atr_prim_qty,
8996 x_qty_available => l_demand_available_qty);
8997
8998 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8999 IF (l_debug = 1) THEN
9000 print_debug('3.5 - Error returned from available_demand_to_reserve API: '
9001 || x_return_status);
9002 END IF;
9003 -- Instead of erroring out and stopping crossdock processing,
9004 -- just delete the demand line from the shopping basket table. Shopping basket
9005 -- table can therefore be a sparsely populated table after running custom logic.
9006 l_shopping_basket_tb.DELETE(i);
9007 GOTO next_custom_demand;
9008 END IF;
9009 ELSE
9010 -- WIP backordered component demand lines always store quantity in the primary UOM
9011 l_demand_atr_prim_qty := l_shopping_basket_tb(i).quantity;
9012 END IF;
9013
9014 -- Convert the ATR primary quantity to the UOM on the demand line
9015 l_demand_uom_code := l_shopping_basket_tb(i).uom_code;
9016 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
9017 l_primary_uom_code, l_demand_uom_code);
9018 IF (l_conversion_rate < 0) THEN
9019 IF (l_debug = 1) THEN
9020 print_debug('3.5 - Error while obtaining Primary UOM conversion rate for demand line');
9021 END IF;
9022 -- Instead of erroring out and stopping crossdock processing,
9023 -- just delete the demand line from the shopping basket table. Shopping basket
9024 -- table can therefore be a sparsely populated table after running custom logic.
9025 l_shopping_basket_tb.DELETE(i);
9026 GOTO next_custom_demand;
9027 END IF;
9028 -- Round the converted quantity to the standard precision
9029 l_demand_atr_qty := ROUND(l_conversion_rate * l_demand_atr_prim_qty, l_conversion_precision);
9030 IF (l_debug = 1) THEN
9031 print_debug('3.5 - Demand line ATR qty: ' || l_demand_atr_qty || ' ' ||
9032 l_demand_uom_code);
9033 END IF;
9034
9035 -- Set the reservable_quantity field to be equal to the ATR quanitty for the
9036 -- current demand line record in the shopping basket.
9037 l_shopping_basket_tb(i).reservable_quantity := l_demand_atr_qty;
9038
9039 <<next_custom_demand>>
9040 NULL; -- Need an executable statment for the branching label above
9041 END LOOP; -- End retrieving ATR quantity for all demand lines in shopping basket table
9042 -- At this stage, the shopping basket table will have the ATR quantity stamped on all of
9043 -- the records. The table can be sparse so the custom logic to sort the shopping basket
9044 -- must keep this in mind. This will be documented in the custom logic API.
9045 l_progress := '430';
9046
9047 -- Call the Custom logic to sort the shopping basket table.
9048 -- If the API is not implemented, the lines will not be sorted at all.
9049 -- {{
9050 -- Test that invalid custom logic to sort demand lines is caught. No sorting
9051 -- should be done if this is the case. }}
9052 IF (l_debug = 1) THEN
9053 print_debug('3.5 - Call the Sort_Demand_Lines API');
9054 END IF;
9055 WMS_XDOCK_CUSTOM_APIS_PUB.Sort_Demand_Lines
9056 (p_move_order_line_id => p_move_order_line_id,
9057 p_prioritize_documents => g_crossdock_criteria_tb(l_crossdock_criteria_id).prioritize_documents_flag,
9058 p_shopping_basket_tb => l_shopping_basket_tb,
9059 x_return_status => x_return_status,
9060 x_msg_count => x_msg_count,
9061 x_msg_data => x_msg_data,
9062 x_api_is_implemented => l_api_is_implemented,
9063 x_sorted_order_tb => l_sorted_order_tb);
9064
9065 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
9066 IF (l_debug = 1) THEN
9067 print_debug('3.5 - Success returned from Sort_Demand_Lines API');
9068 END IF;
9069 ELSE
9070 IF (l_debug = 1) THEN
9071 print_debug('3.5 - Failure returned from Sort_Demand_Lines API');
9072 END IF;
9073 -- In case of exception, do not error out. Just use whatever order the
9074 -- demand lines are in when the shopping basket table was created.
9075 l_sorted_order_tb.DELETE;
9076 END IF;
9077 l_progress := '440';
9078
9079 IF (NOT l_api_is_implemented) THEN
9080 IF (l_debug = 1) THEN
9081 print_debug('3.5 - Custom API is NOT implemented even though Custom Goal is selected!');
9082 END IF;
9083 ELSE
9084 IF (l_debug = 1) THEN
9085 print_debug('3.5 - Custom API is implemented so custom sorting logic is used');
9086 END IF;
9087 END IF;
9088
9089 -- Validate that the output l_sorted_order_tb is not larger in size than
9090 -- the shopping basket table and that values exist in l_sorted_order_tb.
9091 IF (l_debug = 1) THEN
9092 print_debug('3.5 - Rebuild the shopping basket table based on the sorting order returned');
9093 END IF;
9094 IF (l_sorted_order_tb.COUNT > l_shopping_basket_tb.COUNT OR
9095 l_sorted_order_tb.COUNT = 0) THEN
9096 -- Invalid condition from the custom logic API.
9097 -- Do not sort the shopping basket table and just use the current order
9098 -- the lines are in.
9099 IF (l_debug = 1) THEN
9100 print_debug('3.5 - Invalid output from Sort_Demand_Lines API');
9101 print_debug('3.5 - Do not sort the demand lines in the shopping basket');
9102 END IF;
9103 ELSE
9104 -- Sort and rebuild the shopping basket table
9105 l_index := l_sorted_order_tb.FIRST;
9106 -- Initialize the indices used table and the temp shopping basket table
9107 l_indices_used_tb.DELETE;
9108 l_shopping_basket_temp_tb.DELETE;
9109 LOOP
9110 -- Make sure the current entry has not already been used.
9111 -- Also make sure the index refered to in l_sorted_order_tb is a valid one
9112 -- in the shopping basket table.
9113 IF (l_indices_used_tb.EXISTS(l_sorted_order_tb(l_index)) OR
9114 NOT l_shopping_basket_tb.EXISTS(l_sorted_order_tb(l_index))) THEN
9115 IF (l_debug = 1) THEN
9116 print_debug('3.5 - Sorted order table is invalid so do not sort the demand lines');
9117 END IF;
9118 -- Clear the temp shopping basket table
9119 l_shopping_basket_temp_tb.DELETE;
9120 -- Exit out of the loop. No sorting will be done.
9121 GOTO invalid_sorting;
9122 END IF;
9123
9124 -- Mark the current pointer index to the shopping basket table as used
9125 l_indices_used_tb(l_sorted_order_tb(l_index)) := TRUE;
9126
9127 -- Add this entry to the temp shopping basket table.
9128 l_shopping_basket_temp_tb(l_shopping_basket_temp_tb.COUNT + 1) :=
9129 l_shopping_basket_tb(l_sorted_order_tb(l_index));
9130
9131 EXIT WHEN l_index = l_sorted_order_tb.LAST;
9132 l_index := l_sorted_order_tb.NEXT(l_index);
9133 END LOOP;
9134
9135 -- Set the shopping basket table to point to the new sorted one
9136 l_shopping_basket_tb := l_shopping_basket_temp_tb;
9137 l_shopping_basket_temp_tb.DELETE;
9138 IF (l_debug = 1) THEN
9139 print_debug('3.5 - Finished sorting and rebuilding the shopping basket table');
9140 END IF;
9141
9142 -- In case of an invalid sorted order table, jump to this label below and
9143 -- do not sort the shopping basket at all.
9144 <<invalid_sorting>>
9145 NULL; -- Need an executable statement for the above label to work
9146 END IF;
9147 l_progress := '450';
9148
9149 END IF; -- End of crossdocking goal = CUSTOM
9150
9151 -- Section 4: Consume the valid demand lines for crossdocking to the MOL supply
9152 -- 4.1 - Lock the demand line record.
9153 -- 4.2 - Call the available to reserve API to see how much quantity from the demand
9154 -- is valid for crossdocking.
9155 -- 4.3 - Crossdock the demand and supply line records.
9156 -- 4.4 - Create a crossdocked reservation tying the demand to the supply line.
9157
9158 -- Check if there are valid demand lines found for crossdocking.
9159 IF (l_shopping_basket_tb.COUNT = 0) THEN
9160 IF (l_debug = 1) THEN
9161 print_debug('4.1 - No valid demand lines for crossdocking were found');
9162 END IF;
9163 GOTO end_crossdock;
9164 END IF;
9165
9166 -- Initialize the shopping basket demand lines index. This should not be a NULL value.
9167 l_demand_index := NVL(l_shopping_basket_tb.FIRST, 1);
9168
9169 -- Loop through the valid demand lines to crossdock the MOL supply
9170 LOOP
9171 -- Define a savepoint so if an exception occurs while updating database records such as
9172 -- WDD, RSV, or MOL, we need to rollback the changes and stop crossdock processing.
9173 -- Put this inside the demand lines loop so if one demand line is crossdocked successfully
9174 -- but another one errors out, we can still crossdock the first one.
9175 SAVEPOINT Crossdock_Demand_sp;
9176
9177 -- Initialize the variable below used for updating crossdocked WDD records,
9178 -- in case we need to rollback the changes to local PLSQL data structures.
9179 l_xdocked_wdd_index := NULL;
9180
9181 -- Retrieve needed values from the current demand line
9182 l_demand_type_id := l_shopping_basket_tb(l_demand_index).source_type_id;
9183 -- Since the demand type could be WIP or OE, use the same variable to store the
9184 -- header ID. For OE demand lines, this will always refer to the MTL sales order
9185 -- header and not the OE header ID. Currently there is no need to retrieve the
9186 -- OE header ID.
9187 l_demand_header_id := l_shopping_basket_tb(l_demand_index).source_header_id;
9188 l_demand_line_id := l_shopping_basket_tb(l_demand_index).source_line_id;
9189 l_demand_line_detail_id := l_shopping_basket_tb(l_demand_index).source_line_detail_id;
9190 l_demand_qty := l_shopping_basket_tb(l_demand_index).quantity;
9191 l_demand_uom_code := l_shopping_basket_tb(l_demand_index).uom_code;
9192 l_demand_qty2 := l_shopping_basket_tb(l_demand_index).secondary_quantity;
9193 l_demand_uom_code2 := l_shopping_basket_tb(l_demand_index).secondary_uom_code;
9194 l_demand_project_id := l_shopping_basket_tb(l_demand_index).project_id;
9195 l_demand_task_id := l_shopping_basket_tb(l_demand_index).task_id;
9196 l_demand_expected_time := l_shopping_basket_tb(l_demand_index).expected_time;
9197 -- Set the WIP related fields if the demand line is a WIP backordered component demand
9198 IF (l_demand_type_id = 5) THEN
9199 l_wip_entity_id := l_demand_header_id;
9200 l_operation_seq_num := l_demand_line_id;
9201 l_repetitive_schedule_id := l_demand_line_detail_id;
9202 l_wip_supply_type := l_shopping_basket_tb(l_demand_index).wip_supply_type;
9203 ELSE
9204 l_wip_entity_id := NULL;
9205 l_operation_seq_num := NULL;
9206 l_repetitive_schedule_id := NULL;
9207 l_wip_supply_type := NULL;
9208 END IF;
9209
9210 IF (l_debug = 1) THEN
9211 print_debug('4.1 - Current demand line to consider for crossdocking');
9212 print_debug('4.1 - Demand Source Type ID: => ' || l_demand_type_id);
9213 print_debug('4.1 - Demand Header ID: ======> ' || l_demand_header_id);
9214 print_debug('4.1 - Demand Line ID: ========> ' || l_demand_line_id);
9215 print_debug('4.1 - Demand Line Detail ID: => ' || l_demand_line_detail_id);
9216 print_debug('4.1 - Demand Qty: ============> ' || l_demand_qty || ' ' || l_demand_uom_code);
9217 print_debug('4.1 - Secondary Demand Qty: ==> ' || l_demand_qty2 || ' ' || l_demand_uom_code2);
9218 print_debug('4.1 - Demand Project ID: =====> ' || l_demand_project_id);
9219 print_debug('4.1 - Demand Task ID: ========> ' || l_demand_task_id);
9220 print_debug('4.1 - Demand Expected Time: ==> ' ||
9221 TO_CHAR(l_demand_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
9222 print_debug('4.1 - WIP Supply Type: =======> ' || l_wip_supply_type);
9223 END IF;
9224
9225 -- For WIP Discrete Job MOLs, we only want to crossdock to the same
9226 -- OE demand at the Sales Order Line level (Not the WDD level).
9227 -- If the WIP Discrete job was completed for a specific Sales Order demand,
9228 -- then only the WDD records associated with that demand will be populated
9229 -- in the xdock temp table and the shopping basket table. The condition below
9230 -- will thus always be met.
9231
9232 -- If the Discrete job was NOT completed for a particular Sales Order,
9233 -- we will set the l_wip_demand variables to point the OE demand that the WIP
9234 -- MOL was first crossdocked to. Thus afterwards, we will only crossdock to
9235 -- OE WDD demand lines that match the previously crossdocked OE demand.
9236 -- WIP demand will not need to do this check since we do not create reservations
9237 -- for those types of crossdock.
9238 /* 9695544-Now we allow WIP LPN xdock to multiple SO lines. Hence commenting the following code
9239 IF (l_wip_entity_type = 1 AND l_wip_demand_header_id IS NOT NULL
9240 AND l_demand_type_id <> 5) THEN
9241 -- Make sure the current OE demand matches the one we are allowed to crossdock to.
9242 IF (l_demand_type_id <> l_wip_demand_type_id OR
9243 l_demand_header_id <> l_wip_demand_header_id OR
9244 l_demand_line_id <> l_wip_demand_line_id) THEN
9245 IF (l_debug = 1) THEN
9246 print_debug('4.1 - Invalid OE demand to crossdock to for WIP Discrete supply');
9247 END IF;
9248 GOTO next_demand;
9249 END IF;
9250 END IF;
9251 */
9252 -- 4.1 - Lock the demand line record.
9253 -- {{
9254 -- If a demand line cannot be locked, make sure we skip it and do not error out.
9255 -- Just move on to the next available demand. }}
9256 IF (l_demand_type_id IN (2, 8)) THEN
9257 -- OE WDD demand line
9258 BEGIN
9259 OPEN lock_wdd_record(l_demand_line_detail_id);
9260 CLOSE lock_wdd_record;
9261 EXCEPTION
9262 WHEN OTHERS THEN
9263 IF (l_debug = 1) THEN
9264 print_debug('4.1 - Could not lock the WDD demand line record');
9265 END IF;
9266 -- If we cannot lock the supply line, do not error out. Just go to the
9267 -- next available demand and try to crossdock that.
9268 -- Rollback any db changes that might have occurred (currently none).
9269 ROLLBACK TO Crossdock_Demand_sp;
9270 GOTO next_demand;
9271 END;
9272 ELSIF (l_demand_type_id = 5) THEN
9273 -- WIP Backordered Component Demand
9274 BEGIN
9275 OPEN lock_wip_record(l_demand_header_id, l_demand_line_id, l_demand_line_detail_id);
9276 CLOSE lock_wip_record;
9277 EXCEPTION
9278 WHEN OTHERS THEN
9279 IF (l_debug = 1) THEN
9280 print_debug('4.1 - Could not lock the WIP demand line record');
9281 END IF;
9282 -- If we cannot lock the demand line, do not error out. Just go to the
9283 -- next available demand and try to crossdock that.
9284 -- Rollback any db changes that might have occurred (currently none).
9285 ROLLBACK TO Crossdock_Demand_sp;
9286 GOTO next_demand;
9287 END;
9288 ELSE
9289 -- Invalid demand for crossdocking. Should not reach this condition.
9290 -- Rollback any db changes that might have occurred (currently none).
9291 ROLLBACK TO Crossdock_Demand_sp;
9292 GOTO next_demand;
9293 END IF; -- End locking demand line from different source types
9294
9295 IF (l_debug = 1) THEN
9296 print_debug('4.1 - Successfully locked the demand line record');
9297 END IF;
9298 l_progress := '460';
9299
9300 -- 4.2 - Call the available to reserve API to see how much quantity from the demand
9301 -- is valid for crossdocking.
9302 -- The quantity_backordered on the WIP demand is the same as
9303 -- the ATR qty so it is fully reserveable.
9304 IF (l_demand_type_id <> 5) THEN
9305 IF (l_debug = 1) THEN
9306 print_debug('4.2 - Call the Available_demand_to_reserve API');
9307 END IF;
9308 INV_RESERVATION_AVAIL_PVT.Available_demand_to_reserve
9309 (p_api_version_number => 1.0,
9310 p_init_msg_lst => fnd_api.g_false,
9311 x_return_status => x_return_status,
9312 x_msg_count => x_msg_count,
9313 x_msg_data => x_msg_data,
9314 p_primary_uom_code => l_primary_uom_code,
9315 p_demand_source_type_id => l_demand_type_id,
9316 p_demand_source_header_id => l_demand_header_id,
9317 p_demand_source_line_id => l_demand_line_id,
9318 p_demand_source_line_detail => l_demand_line_detail_id,
9319 p_project_id => l_demand_project_id,
9320 p_task_id => l_demand_task_id,
9321 x_qty_available_to_reserve => l_demand_atr_prim_qty,
9322 x_qty_available => l_demand_available_qty);
9323
9324 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9325 IF (l_debug = 1) THEN
9326 print_debug('4.2 - Error returned from available_demand_to_reserve API: '
9327 || x_return_status);
9328 END IF;
9329 -- Rollback any db changes that might have occurred (currently none).
9330 ROLLBACK TO Crossdock_Demand_sp;
9331 GOTO next_demand;
9332 END IF;
9333 ELSE
9334 -- WIP backordered component demand lines always store quantity in the primary UOM
9335 l_demand_atr_prim_qty := l_demand_qty;
9336 END IF;
9337
9338 -- Convert the ATR primary quantity to the UOM on the demand line
9339 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
9340 l_primary_uom_code, l_demand_uom_code);
9341 IF (l_conversion_rate < 0) THEN
9342 IF (l_debug = 1) THEN
9343 print_debug('4.2 - Error while obtaining Primary UOM conversion rate for demand line');
9344 END IF;
9345 -- Rollback any db changes that might have occurred (currently none).
9346 ROLLBACK TO Crossdock_Demand_sp;
9347 GOTO next_demand;
9348 END IF;
9349 -- Round the converted quantity to the standard precision
9350 l_demand_atr_qty := ROUND(l_conversion_rate * l_demand_atr_prim_qty, l_conversion_precision);
9351
9352 -- Set the reservable quantity field for the current demand line
9353 -- in the shopping basket table.
9354 l_shopping_basket_tb(l_demand_index).reservable_quantity := l_demand_atr_qty;
9355
9356 IF (l_debug = 1) THEN
9357 print_debug('4.2 - Demand line ATR qty: ' || l_demand_atr_qty || ' ' ||
9358 l_demand_uom_code);
9359 END IF;
9360 -- If the current demand line has no reservable quantity,
9361 -- skip it and go to the next available demand line.
9362 -- {{
9363 -- Test for an available demand line for crossdocking that has no available quantity
9364 -- to reserve. This line is already satisfied by another existing reservation. }}
9365 IF (l_demand_atr_qty <= 0) THEN
9366 IF (l_debug = 1) THEN
9367 print_debug('4.2 - Demand ATR qty <= 0 so skip to next available demand');
9368 END IF;
9369 -- Rollback any db changes that might have occurred (currently none).
9370 ROLLBACK TO Crossdock_Demand_sp;
9371 GOTO next_demand;
9372 END IF;
9373 l_progress := '470';
9374
9375 -- 4.3 - Crossdock the demand and supply line records.
9376 IF (l_debug = 1) THEN
9377 print_debug('4.3 - Crossdock the demand and supply line records');
9378 END IF;
9379
9380 -- Convert the WDD ATR qty to the UOM on the MOL supply line. This value should not be zero
9381 -- if we have reached this point. Also convert the WDD qty to the UOM on the supply line.
9382 -- Since they use the same conversion rate, we just need to retrieve that value once.
9383 -- This is required so we know if the WDD line needs to be split or not. That would depend
9384 -- on the WDD qty, not the WDD ATR qty.
9385 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
9386 l_demand_uom_code, l_supply_uom_code);
9387 IF (l_conversion_rate < 0) THEN
9388 IF (l_debug = 1) THEN
9389 print_debug('4.3 - Error while obtaining UOM conversion rate for WDD/WIP qty');
9390 END IF;
9391 -- Rollback any db changes that might have occurred (currently none).
9392 ROLLBACK TO Crossdock_Demand_sp;
9393 GOTO next_demand;
9394 END IF;
9395 -- Round the converted quantity to the standard precision
9396 l_wdd_atr_txn_qty := ROUND(l_conversion_rate * l_demand_atr_qty, l_conversion_precision);
9397 l_wdd_txn_qty := ROUND(l_conversion_rate * l_demand_qty, l_conversion_precision);
9398 IF (l_debug = 1) THEN
9399 print_debug('4.3 - WDD/WIP ATR txn qty: => ' || l_wdd_atr_txn_qty || ' ' || l_supply_uom_code);
9400 print_debug('4.3 - WDD/WIP txn qty: =====> ' || l_wdd_txn_qty || ' ' || l_supply_uom_code);
9401 END IF;
9402 l_progress := '480';
9403
9404 -- Calculate the Available to Detail quantity.
9405 -- {{
9406 -- Test that the available to detail quantity is calculated properly,
9407 -- i.e. is lower than WDD/WIP ATR qty and supply line qty, and is an integer value if
9408 -- UOM integrity = 'Y'. }}
9409 IF (g_crossdock_criteria_tb(l_crossdock_criteria_id).uom_integrity_flag = 1) THEN
9410 -- UOM Integrity is 'Yes'
9411 l_atd_qty := LEAST(FLOOR(l_wdd_atr_txn_qty), FLOOR(l_supply_atr_qty));
9412 ELSE
9413 -- UOM Integrity is 'No'
9414 l_atd_qty := LEAST(l_wdd_atr_txn_qty, l_supply_atr_qty);
9415 END IF;
9416 IF (l_debug = 1) THEN
9417 print_debug('4.3 - Available to detail qty: ' || l_atd_qty || ' ' ||
9418 l_supply_uom_code);
9419 END IF;
9420 -- If the ATD qty is 0, then goto the next available demand line to crossdock.
9421 -- This is possible if the UOM integrity flag is 'Y' and the resultant quantities
9422 -- were floored to 0.
9423 -- {{
9424 -- Test for ATD qty = 0. This can come about if UOM integrity is Yes and the
9425 -- demand line with available to reserve qty gets floored to 0. }}
9426 IF (l_atd_qty = 0) THEN
9427 IF (l_debug = 1) THEN
9428 print_debug('4.3 - ATD qty = 0 so skip to the next available demand');
9429 END IF;
9430 -- Rollback any db changes that might have occurred (currently none).
9431 ROLLBACK TO Crossdock_Demand_sp;
9432 GOTO next_demand;
9433 END IF;
9434 l_progress := '490';
9435
9436 -- Convert l_atd_qty to the primary UOM
9437 l_conversion_rate := get_conversion_rate(l_inventory_item_id,
9438 l_supply_uom_code, l_primary_uom_code);
9439 IF (l_conversion_rate < 0) THEN
9440 IF (l_debug = 1) THEN
9441 print_debug('4.3 - Error while obtaining primary UOM conversion rate for ATD qty');
9442 END IF;
9443 -- Rollback any db changes that might have occurred (currently none).
9444 ROLLBACK TO Crossdock_Demand_sp;
9445 GOTO next_demand;
9446 END IF;
9447 -- Convert l_atd_qty to the primary UOM
9448 -- Bug 5608611: Use quantity from demand document where possible
9449 IF (l_atd_qty = l_wdd_atr_txn_qty AND l_demand_uom_code = l_primary_uom_code) THEN
9450 l_atd_prim_qty := l_demand_atr_qty;
9451 ELSE
9452 -- Round the converted quantity to the standard precision
9453 l_atd_prim_qty := ROUND(l_conversion_rate * l_atd_qty, l_conversion_precision);
9454 END IF;
9455 IF (l_debug = 1) THEN
9456 print_debug('4.3 - ATD qty in primary UOM: => ' || l_atd_prim_qty || ' ' ||
9457 l_primary_uom_code);
9458 END IF;
9459 l_progress := '500';
9460
9461 -- Crossdock the WDD/WIP demand record
9462 IF (l_demand_type_id <> 5) THEN
9463 -- Crossdock the WDD record, splitting it if necessary.
9464 IF (l_debug = 1) THEN
9465 print_debug('4.3 - Call the Crossdock_WDD API to crossdock/split the WDD');
9466 END IF;
9467 Crossdock_WDD
9468 (p_log_prefix => '4.3 - ',
9469 p_crossdock_type => G_CRT_TYPE_OPP,
9470 p_batch_id => l_batch_id,
9471 p_wsh_release_table => l_wsh_release_table,
9472 p_trolin_delivery_ids => l_trolin_delivery_ids,
9473 p_del_detail_id => l_del_detail_id,
9474 l_wdd_index => l_dummy_wdd_index,
9475 l_debug => l_debug,
9476 l_inventory_item_id => l_inventory_item_id,
9477 l_wdd_txn_qty => l_wdd_txn_qty,
9478 l_atd_qty => l_atd_qty,
9479 l_atd_wdd_qty => l_atd_wdd_qty,
9480 l_atd_wdd_qty2 => l_atd_wdd_qty2,
9481 l_supply_uom_code => l_supply_uom_code,
9482 l_demand_uom_code => l_demand_uom_code,
9483 l_demand_uom_code2 => l_demand_uom_code2,
9484 l_conversion_rate => l_conversion_rate,
9485 l_conversion_precision => l_conversion_precision,
9486 l_demand_line_detail_id => l_demand_line_detail_id,
9487 l_index => l_index,
9488 l_detail_id_tab => l_detail_id_tab,
9489 l_action_prms => l_action_prms,
9490 l_action_out_rec => l_action_out_rec,
9491 l_split_wdd_id => l_split_wdd_id,
9492 l_detail_info_tab => l_detail_info_tab,
9493 l_in_rec => l_in_rec,
9494 l_out_rec => l_out_rec,
9495 l_mol_line_id => l_mol_line_id,
9496 l_split_wdd_index => l_split_wdd_index,
9497 l_split_delivery_index => l_split_delivery_index,
9498 l_split_wdd_rel_rec => l_split_wdd_rel_rec,
9499 l_allocation_method => l_allocation_method,
9500 l_demand_qty => l_demand_qty,
9501 l_demand_qty2 => l_demand_qty2,
9502 l_demand_atr_qty => l_demand_atr_qty,
9503 l_xdocked_wdd_index => l_xdocked_wdd_index,
9504 l_supply_type_id => l_supply_type_id,
9505 x_return_status => x_return_status,
9506 x_msg_count => x_msg_count,
9507 x_msg_data => x_msg_data,
9508 x_error_code => l_error_code
9509 );
9510
9511 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9512 IF (l_debug = 1) THEN
9513 print_debug('4.3 - Error returned from Crossdock_WDD API: '
9514 || x_return_status);
9515 END IF;
9516 --RAISE fnd_api.g_exc_error;
9517 -- If an exception occurs while modifying a database record, rollback the changes
9518 -- and just go to the next available demand to crossdock
9519 ROLLBACK TO Crossdock_Demand_sp;
9520 -- We need to also rollback changes done to local PLSQL data structures
9521 IF (l_xdocked_wdd_index IS NOT NULL) THEN
9522 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
9523 END IF;
9524 GOTO next_demand;
9525 ELSE
9526 IF (l_debug = 1) THEN
9527 print_debug('4.3 - Successfully crossdocked/split the WDD record');
9528 END IF;
9529 END IF;
9530 l_progress := '510';
9531
9532 ELSE
9533 -- Crossdock the WIP demand record.
9534 -- {{
9535 -- Verify that the WIP API properly allocates the crossdocked material when
9536 -- the demand is WIP. }}
9537 IF (l_debug = 1) THEN
9538 print_debug('4.3 - Call wip_picking_pub.allocate_material to crossdock the WIP demand');
9539 END IF;
9540 wip_picking_pub.allocate_material
9541 (p_wip_entity_id => l_wip_entity_id,
9542 p_operation_seq_num => l_operation_seq_num,
9543 p_inventory_item_id => l_inventory_item_id,
9544 p_repetitive_schedule_id => l_repetitive_schedule_id,
9545 p_primary_quantity => l_atd_prim_qty,
9546 x_quantity_allocated => l_wip_qty_allocated,
9547 x_return_status => x_return_status,
9548 x_msg_data => x_msg_data
9549 );
9550
9551 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS OR l_wip_qty_allocated = 0) THEN
9552 IF (l_debug = 1) THEN
9553 print_debug('4.3 - Error returned from wip_picking_pub.allocate_material API: '
9554 || x_return_status);
9555 END IF;
9556 --RAISE fnd_api.g_exc_error;
9557 -- If an exception occurs while modifying a database record, rollback the changes
9558 -- and just go to the next available demand to crossdock
9559 ROLLBACK TO Crossdock_Demand_sp;
9560 GOTO next_demand;
9561 ELSE
9562 IF (l_debug = 1) THEN
9563 print_debug('4.3 - Successfully crossdocked the WIP demand');
9564 END IF;
9565 END IF;
9566 l_progress := '515';
9567 END IF;
9568
9569
9570 -- Crossdock the MOL supply line, splitting it if necessary
9571 IF (l_debug = 1) THEN
9572 print_debug('4.3 - Call the Crossdock_MOL API to crossdock/split the MOL');
9573 END IF;
9574 Crossdock_MOL
9575 (p_log_prefix => '4.3 - ',
9576 p_crossdock_type => G_CRT_TYPE_OPP,
9577 l_debug => l_debug,
9578 l_inventory_item_id => l_inventory_item_id,
9579 l_mol_qty => l_mol_qty,
9580 l_mol_qty2 => l_mol_qty2,
9581 l_atd_qty => l_atd_qty,
9582 l_atd_mol_qty2 => l_atd_mol_qty2,
9583 l_supply_uom_code => l_supply_uom_code,
9584 l_mol_uom_code2 => l_mol_uom_code2,
9585 l_conversion_rate => l_conversion_rate,
9586 l_conversion_precision => l_conversion_precision,
9587 l_mol_prim_qty => l_mol_prim_qty,
9588 l_atd_prim_qty => l_atd_prim_qty,
9589 l_split_wdd_id => l_split_wdd_id,
9590 l_mol_header_id => l_mol_header_id,
9591 l_mol_line_id => l_mol_line_id,
9592 l_supply_atr_qty => l_supply_atr_qty,
9593 l_demand_type_id => l_demand_type_id,
9594 l_wip_entity_id => l_wip_entity_id,
9595 l_operation_seq_num => l_operation_seq_num,
9596 l_repetitive_schedule_id => l_repetitive_schedule_id,
9597 l_wip_supply_type => l_wip_supply_type,
9598 l_xdocked_wdd_index => l_xdocked_wdd_index,
9599 l_detail_info_tab => l_detail_info_tab,
9600 l_wdd_index => l_dummy_wdd_index,
9601 l_split_wdd_index => l_split_wdd_index,
9602 p_wsh_release_table => l_wsh_release_table,
9603 l_supply_type_id => l_supply_type_id,
9604 x_return_status => x_return_status,
9605 x_msg_count => x_msg_count,
9606 x_msg_data => x_msg_data,
9607 x_error_code => l_error_code,
9608 x_new_mol_id => l_new_mol_id , --9695544
9609 l_criterion_type => G_CRT_TYPE_OPP
9610 );
9611
9612 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9613 IF (l_debug = 1) THEN
9614 print_debug('4.3 - Error returned from Crossdock_MOL API: '
9615 || x_return_status);
9616 END IF;
9617 --RAISE fnd_api.g_exc_error;
9618 -- If an exception occurs while modifying a database record, rollback the changes
9619 -- and just go to the next WDD record or supply to crossdock.
9620 ROLLBACK TO Crossdock_Demand_sp;
9621 -- We need to also rollback changes done to local PLSQL data structures
9622 IF (l_xdocked_wdd_index IS NOT NULL) THEN
9623 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
9624 END IF;
9625 GOTO next_demand;
9626 ELSE
9627 IF (l_debug = 1) THEN
9628 print_debug('4.3 - Successfully crossdocked/split the MOL record');
9629 END IF;
9630 END IF;
9631 l_progress := '520';
9632
9633 IF ( NVL(l_new_mol_id,0) > 0 ) THEN
9634 --9695544-Add this MOL and xdock criteria in global pl/sq table
9635 WMS_Cross_Dock_Pvt.insert_xdock_criteria( l_new_mol_id,l_crossdock_criteria_id,x_return_status,x_msg_data,x_msg_count);
9636 END IF;
9637 -- 4.4 - Create a crossdocked reservation tying the demand to the supply line.
9638 -- Calculate the supply expected time
9639 IF (l_debug = 1) THEN
9640 print_debug('4.4 - Create a crossdock reservation peg to tie the demand to the supply');
9641 END IF;
9642
9643 -- Call the Create_RSV API to create a crossdock reservation.
9644 -- Do this only for OE demand, not WIP.
9645 -- For WIP supply, create a reservation only if the WIP entity type is 'Discrete'.
9646 -- Flow WIP LPN completions should not create reservations here. They are created
9647 -- immediately upon flow schedule completion against onhand Inventory.
9648 IF (l_demand_type_id <> 5 AND
9649 (l_wip_entity_type IS NULL OR l_wip_entity_type = 1)) THEN
9650 IF (l_debug = 1) THEN
9651 print_debug('4.4 - Call the Create_RSV API to create a crossdock reservation');
9652 END IF;
9653 Create_RSV
9654 (p_log_prefix => '4.4 - ',
9655 p_crossdock_type => G_CRT_TYPE_OPP,
9656 l_debug => l_debug,
9657 l_organization_id => l_organization_id,
9658 l_inventory_item_id => l_inventory_item_id,
9659 l_demand_type_id => l_demand_type_id,
9660 l_demand_so_header_id => l_demand_header_id, -- Use this value here for Opportunistic
9661 l_demand_line_id => l_demand_line_id,
9662 l_split_wdd_id => l_split_wdd_id,
9663 l_primary_uom_code => l_primary_uom_code,
9664 l_demand_uom_code2 => l_demand_uom_code2,
9665 l_supply_uom_code => l_supply_uom_code,
9666 l_atd_qty => l_atd_qty,
9667 l_atd_prim_qty => l_atd_prim_qty,
9668 l_atd_wdd_qty2 => l_atd_wdd_qty2,
9669 l_supply_type_id => l_supply_type_id,
9670 l_supply_header_id => l_supply_header_id,
9671 l_supply_line_id => l_supply_line_id,
9672 l_supply_line_detail_id => l_supply_line_detail_id,
9673 l_crossdock_criteria_id => l_crossdock_criteria_id,
9674 l_supply_expected_time => l_supply_expected_time,
9675 l_demand_expected_time => l_demand_expected_time,
9676 l_demand_project_id => l_demand_project_id,
9677 l_demand_task_id => l_demand_task_id,
9678 l_original_rsv_rec => l_original_rsv_rec,
9679 l_original_serial_number => l_original_serial_number,
9680 l_to_serial_number => l_to_serial_number,
9681 l_quantity_reserved => l_quantity_reserved,
9682 l_quantity_reserved2 => l_quantity_reserved2,
9683 l_rsv_id => l_rsv_id,
9684 x_return_status => x_return_status,
9685 x_msg_count => x_msg_count,
9686 x_msg_data => x_msg_data
9687 );
9688
9689 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9690 IF (l_debug = 1) THEN
9691 print_debug('4.4 - Error returned from create_reservation API: '
9692 || x_return_status);
9693 END IF;
9694 --RAISE fnd_api.g_exc_error;
9695 -- If an exception occurs while modifying a database record, rollback the changes
9696 -- and just go to the next WDD record to crossdock.
9697 ROLLBACK TO Crossdock_Demand_sp;
9698 -- We need to also rollback changes done to local PLSQL data structures
9699 IF (l_xdocked_wdd_index IS NOT NULL) THEN
9700 l_detail_info_tab.DELETE(l_xdocked_wdd_index);
9701 END IF;
9702 GOTO next_demand;
9703 ELSE
9704 IF (l_debug = 1) THEN
9705 print_debug('4.4 - Successfully created a crossdock RSV record');
9706 END IF;
9707 END IF;
9708 END IF;
9709 l_progress := '530';
9710
9711 -- If the supply is a WIP discrete job, we only want to create reservation pegs
9712 -- tying the WIP job to the same OE Sales Order Line demand. The user can manually
9713 -- create multiple ones for the same WIP job to different OE demand from
9714 -- the reservations form, but from the crossdock pegging logic, we want to restrict this.
9715 -- The reason is due to WIP not having the logic to know which reservation to consume
9716 -- when the WIP job LPN is being putaway. If we have reached this point, a crossdock
9717 -- peg has already been created. Set the l_wip_demand variables so we will only
9718 -- crossdock to that OE demand. (You can have multiple WDD records for the same SO line).
9719
9720 IF (l_wip_entity_type = 1 AND l_wip_demand_header_id IS NULL) THEN
9721 IF (l_demand_type_id <> 5) THEN
9722 -- OE demand that was just crossdocked for WIP Discrete supply.
9723 -- We want to restrict future crossdock pegs to only go against this same demand.
9724 l_wip_demand_type_id := l_demand_type_id;
9725 l_wip_demand_header_id := l_demand_header_id;
9726 l_wip_demand_line_id := l_demand_line_id;
9727 IF (l_debug = 1) THEN
9728 print_debug('4.4 - Supply is a WIP Discrete job and a crossdock has occurred');
9729 -- print_debug('4.4 - Unique OE demand we are ONLY allowed to peg to');
9730 print_debug('4.4 - Demand Type ID: ===> ' || l_wip_demand_type_id);
9731 print_debug('4.4 - Demand Header ID: => ' || l_wip_demand_header_id);
9732 print_debug('4.4 - Demand Line ID: ===> ' || l_wip_demand_line_id);
9733 END IF;
9734 END IF;
9735 END IF;
9736
9737
9738 -- Exit out of available demand lines loop if the MOL supply has been fully crossdocked.
9739 -- There is no need to consider anymore demand lines for crossdocking.
9740 IF (l_supply_atr_qty <= 0) THEN
9741 EXIT;
9742 END IF;
9743
9744 <<next_demand>>
9745 -- Exit when all demand lines have been considered
9746 EXIT WHEN l_demand_index = l_shopping_basket_tb.LAST;
9747 l_demand_index := l_shopping_basket_tb.NEXT(l_demand_index);
9748 END LOOP; -- End looping through demand lines in shopping basket table
9749 l_progress := '540';
9750
9751 -- Done with crossdocking logic
9752 -- This label should come before the post crossdocking logic to update WDD records.
9753 -- If the MOL is completely used to fulfill an existing reservation, we will go to
9754 -- this label and the logic to update the WDD records needs to be done.
9755 <<end_crossdock>>
9756
9757 -- Section 5: Post crossdocking logic
9758 -- 5.1 - For all crossdocked WDD lines, call the shipping API to update the
9759 -- released_status and move_order_line_id columns.
9760 -- 5.2 - Bug 5194761: clear the temp table wms_xdock_pegging_gtmp
9761 -- {{
9762 -- Make sure the shipping API to update crossdocked WDD lines is only called if necessary
9763 -- and properly updates the WDD records. }}
9764 IF (l_detail_info_tab.COUNT > 0) THEN
9765 IF (l_debug = 1) THEN
9766 print_debug('5.1 - Call the Create_Update_Delivery_Detail API for ' ||
9767 l_detail_info_tab.COUNT || ' crossdocked WDD records');
9768 END IF;
9769
9770 l_in_rec.caller := 'WMS_XDOCK_PEGGING_PUB';
9771 l_in_rec.action_code := 'UPDATE';
9772
9773 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
9774 (p_api_version_number => 1.0,
9775 p_init_msg_list => fnd_api.g_false,
9776 p_commit => fnd_api.g_false,
9777 x_return_status => x_return_status,
9778 x_msg_count => x_msg_count,
9779 x_msg_data => x_msg_data,
9780 p_detail_info_tab => l_detail_info_tab,
9781 p_in_rec => l_in_rec,
9782 x_out_rec => l_out_rec
9783 );
9784
9785 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9786 IF (l_debug = 1) THEN
9787 print_debug('5.1 - Error returned from Create_Update_Delivery_Detail API: '
9788 || x_return_status);
9789 END IF;
9790 RAISE FND_API.G_EXC_ERROR;
9791 ELSE
9792 IF (l_debug = 1) THEN
9793 print_debug('5.1 - Successfully updated the crossdocked WDD records');
9794 END IF;
9795 END IF;
9796 END IF;
9797 l_progress := '550';
9798
9799 -- Bug 5194761: delete records from wms_xdock_pegging_gtmp
9800 DELETE wms_xdock_pegging_gtmp;
9801 IF (l_debug = 1) AND SQL%FOUND THEN
9802 print_debug('5.2 - Cleared the temp table wms_xdock_pegging_gtmp');
9803 END IF;
9804
9805 -- If we have reached this point, the return status should be set to success.
9806 -- This variable is reused each time we call another API but we try to continue with the
9807 -- flow and raise an exception only when absolutely necessary. Since this is a planning
9808 -- and pegging API, if exceptions occur, we should just not peg anything instead of throwing
9809 -- errors.
9810 x_return_status := fnd_api.g_ret_sts_success;
9811 l_progress := '560';
9812
9813 IF (l_debug = 1) THEN
9814 print_debug('***End of Opportunistic_Cross_Dock***');
9815 END IF;
9816
9817 -- Stop the profiler
9818 -- dbms_profiler.stop_profiler;
9819
9820 EXCEPTION
9821 WHEN FND_API.G_EXC_ERROR THEN
9822 ROLLBACK TO Opportunistic_Cross_Dock_sp;
9823 x_return_status := fnd_api.g_ret_sts_error;
9824 fnd_msg_pub.count_and_get(p_count => x_msg_count,
9825 p_data => x_msg_data);
9826 IF (l_debug = 1) THEN
9827 print_debug('Exiting Opportunistic_Cross_Dock - Execution error: ' ||
9828 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
9829 END IF;
9830
9831 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
9832 ROLLBACK TO Opportunistic_Cross_Dock_sp;
9833 x_return_status := fnd_api.g_ret_sts_unexp_error;
9834 fnd_msg_pub.count_and_get(p_count => x_msg_count,
9835 p_data => x_msg_data);
9836 IF (l_debug = 1) THEN
9837 print_debug('Exiting Opportunistic_Cross_Dock - Unexpected error: ' ||
9838 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
9839 END IF;
9840
9841 WHEN OTHERS THEN
9842 ROLLBACK TO Opportunistic_Cross_Dock_sp;
9843 x_return_status := fnd_api.g_ret_sts_unexp_error;
9844 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
9845 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
9846 END IF;
9847 fnd_msg_pub.count_and_get(p_count => x_msg_count,
9848 p_data => x_msg_data);
9849 IF (l_debug = 1) THEN
9850 print_debug('Exiting Opportunistic_Cross_Dock - Others exception: ' ||
9851 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
9852 END IF;
9853
9854 END Opportunistic_Cross_Dock;
9855 -- {{ }}
9856 -- {{******************** End Opportunistic_Cross_Dock ********************}}
9857 -- {{ }}
9858
9859
9860 -- p_source_type_id refers to new lookup_type in mfg_lookups called 'Reservation_Types'
9861 -- Valid supplies:
9862 -- 1 - Purchase Order
9863 -- 7 - Internal Requisition
9864 -- 25 - ASN
9865 -- 26 - In Transit Shipment
9866 -- Valid demands:
9867 -- 2 - Sales Order
9868 -- 8 - Internal Order
9869 -- Supply of type Receiving is material already received so there is no need to get an expected
9870 -- receipt time for that. SYSDATE at the time the crossdock peg is created will be used and stamped
9871 -- on the reservation. Demand of type WIP (backordered component demand) will always use the
9872 -- date_required field in the view wip_material_shortages_v as the expected ship time. Other
9873 -- source types will not currently be supported in this API.
9874 -- {{ }}
9875 -- {{******************** Procedure Get_Expected_Time ********************}}
9876 PROCEDURE Get_Expected_Time
9877 (p_source_type_id IN NUMBER,
9878 p_source_header_id IN NUMBER,
9879 p_source_line_id IN NUMBER,
9880 p_source_line_detail_id IN NUMBER,
9881 p_supply_or_demand IN NUMBER,
9882 p_crossdock_criterion_id IN NUMBER,
9883 x_return_status OUT NOCOPY VARCHAR2,
9884 x_msg_count OUT NOCOPY NUMBER,
9885 x_msg_data OUT NOCOPY VARCHAR2,
9886 x_dock_start_time OUT NOCOPY DATE,
9887 x_dock_mean_time OUT NOCOPY DATE,
9888 x_dock_end_time OUT NOCOPY DATE,
9889 x_expected_time OUT NOCOPY DATE)
9890 IS
9891 l_api_name CONSTANT VARCHAR2(30) := 'Get_Expected_Time';
9892 l_progress VARCHAR2(10);
9893 l_debug NUMBER := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
9894
9895 -- This variable is used to indicate if the custom API was used to determine
9896 -- the expected time values.
9897 l_api_is_implemented BOOLEAN;
9898
9899 -- Cursor to retrieve the trip stop id, carrier id, and expected ship time
9900 -- (without considering dock appointments) for a WDD demand line.
9901 -- The order to look for this information is documented in the Crossdock Pegging TDD.
9902 -- Make use of outer joins in a cascading manner since records might not exist in all
9903 -- of the tables. WSH_DELIVERY_LEGS could have multiple trip stops for the same delivery.
9904 -- For our purposes, we want to pick the first one, hence choose the one with the minimum
9905 -- value for the sequence_number. This is contingent upon a delivery being present for
9906 -- the WDD demand line. For WDD demand lines, reservations will store the mtl sales order
9907 -- header ID, OE order line ID, and WDD delivery detail ID as the source header ID, line ID,
9908 -- and line detail ID respectively.
9909 CURSOR wdd_rec_cursor IS
9910 SELECT wdd.organization_id AS organization_id,
9911 wts.stop_id AS trip_stop_id,
9912 NVL(wt.carrier_id,
9913 NVL(NVL(wnd.carrier_id, wcs_wnd.carrier_id),
9914 NVL(NVL(wdd.carrier_id, wcs_wdd.carrier_id),
9915 NVL(wc_ool.carrier_id, wcs_ool.carrier_id)))) AS carrier_id,
9916 NVL(wts.planned_departure_date,
9917 NVL(wdd.date_scheduled,
9918 NVL(ool.schedule_ship_date, ool.promise_date))) AS expected_ship_date
9919 FROM wsh_delivery_details wdd, oe_order_lines_all ool,
9920 wsh_delivery_assignments_v wda, wsh_new_deliveries wnd, wsh_delivery_legs wdl,
9921 wsh_trip_stops wts, wsh_trips wt, wsh_carrier_services wcs_wnd,
9922 wsh_carrier_services wcs_wdd, wsh_carrier_services wcs_ool, wsh_carriers wc_ool
9923 WHERE wdd.delivery_detail_id = p_source_line_detail_id
9924 AND ool.line_id = p_source_line_id
9925 AND wdd.source_line_id = ool.line_id
9926 AND inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) = p_source_header_id
9927 AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
9928 AND wda.delivery_id = wnd.delivery_id (+)
9929 AND wnd.delivery_id = wdl.delivery_id (+)
9930 AND (wdl.sequence_number IS NULL OR
9931 wdl.sequence_number = (SELECT MIN(sequence_number)
9932 FROM wsh_delivery_legs wdl_first_leg
9933 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
9934 AND wdl.pick_up_stop_id = wts.stop_id (+)
9935 AND wts.trip_id = wt.trip_id (+)
9936 AND wnd.ship_method_code = wcs_wnd.ship_method_code (+)
9937 AND wdd.ship_method_code = wcs_wdd.ship_method_code (+)
9938 AND ool.shipping_method_code = wcs_ool.ship_method_code (+)
9939 AND ool.freight_carrier_code = wc_ool.freight_code (+);
9940
9941
9942 -- Cursor to retrieve the trip stop id, carrier id, and expected receipt time
9943 -- (without considering dock appointments) for a PO supply line.
9944 -- For PO supply lines, reservations will store the PO header ID, PO line location ID,
9945 -- and NULL as the source header ID, line ID, and line detail ID respectively.
9946 -- NOTE REGARDING INBOUND TRIPS:
9947 -- Currently, when an Inbound Trip is created, the trip has a planned arrival date
9948 -- set to be the last accept date for the inbound supply. When a shipment is created,
9949 -- the planned arrival date of the trip does not get updated. Thus the expected
9950 -- receipt date returned from this cursor is not the most accurate until the issue
9951 -- with trips is resolved.
9952 CURSOR po_rec_cursor IS
9953 SELECT poll.ship_to_organization_id AS organization_id,
9954 wts.stop_id AS trip_stop_id,
9955 NVL(wt.carrier_id,
9956 NVL(NVL(wnd.carrier_id, wcs_wnd.carrier_id),
9957 NVL(NVL(wdd.carrier_id, wcs_wdd.carrier_id),
9958 wc_poll.carrier_id))) AS carrier_id,
9959 NVL(wts.planned_arrival_date,
9960 NVL(poll.promised_date, poll.need_by_date)) AS expected_receipt_date
9961 FROM po_line_locations_all poll, wsh_delivery_details wdd,
9962 wsh_delivery_assignments_v wda, wsh_new_deliveries wnd, wsh_delivery_legs wdl,
9963 wsh_trip_stops wts, wsh_trips wt, wsh_carrier_services wcs_wnd,
9964 wsh_carrier_services wcs_wdd, wsh_carriers wc_poll
9965 WHERE poll.po_header_id = p_source_header_id
9966 AND poll.line_location_id = p_source_line_id
9967 AND poll.po_header_id = wdd.source_header_id (+)
9968 AND poll.po_line_id = wdd.source_line_id (+)
9969 AND poll.line_location_id = wdd.po_shipment_line_id (+)
9970 AND 'PO' = wdd.source_code (+)
9971 AND 'I' = wdd.line_direction (+)
9972 AND 'L' <> wdd.released_status (+)
9973 AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
9974 AND wda.delivery_id = wnd.delivery_id (+)
9975 AND wnd.delivery_id = wdl.delivery_id (+)
9976 AND (wdl.sequence_number IS NULL OR
9977 wdl.sequence_number = (SELECT MIN(sequence_number)
9978 FROM wsh_delivery_legs wdl_first_leg
9979 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
9980 AND wdl.drop_off_stop_id = wts.stop_id (+)
9981 AND wts.trip_id = wt.trip_id (+)
9982 AND wnd.ship_method_code = wcs_wnd.ship_method_code (+)
9983 AND wdd.ship_method_code = wcs_wdd.ship_method_code (+)
9984 AND poll.ship_via_lookup_code = wc_poll.freight_code (+)
9985 ORDER BY expected_receipt_date ASC;
9986
9987
9988 -- Cursor to retrieve the trip stop id, carrier id, and expected receipt time
9989 -- (without considering dock appointments) for an ASN supply line.
9990 -- For ASN supply lines, reservations will store the PO header ID, PO line location ID,
9991 -- and RCV shipment line ID as the source header ID, line ID, and line detail ID respectively.
9992 -- NOTE REGARDING INBOUND TRIPS:
9993 -- Currently, when an Inbound Trip is created, the trip has a planned arrival date
9994 -- set to be the last accept date for the inbound supply. When a shipment is created,
9995 -- the planned arrival date of the trip does not get updated. Thus the expected
9996 -- receipt date returned from this cursor is not the most accurate until the issue
9997 -- with trips is resolved.
9998 CURSOR asn_rec_cursor IS
9999 SELECT rsl.to_organization_id AS organization_id,
10000 wts.stop_id AS trip_stop_id,
10001 NVL(wt.carrier_id,
10002 NVL(NVL(wnd.carrier_id, wcs_wnd.carrier_id),
10003 NVL(NVL(wdd.carrier_id, wcs_wdd.carrier_id),
10004 NVL(wc_rsh.carrier_id,
10005 wc_poll.carrier_id)))) AS carrier_id,
10006 NVL(wts.planned_arrival_date,
10007 NVL(NVL(rsh.expected_receipt_date, rsh.shipped_date),
10008 NVL(poll.promised_date, poll.need_by_date))) AS expected_receipt_date
10009 FROM po_line_locations_all poll, wsh_delivery_details wdd,
10010 rcv_shipment_headers rsh, rcv_shipment_lines rsl,
10011 wsh_delivery_assignments_v wda, wsh_new_deliveries wnd, wsh_delivery_legs wdl,
10012 wsh_trip_stops wts, wsh_trips wt, wsh_carrier_services wcs_wnd,
10013 wsh_carrier_services wcs_wdd, wsh_carriers wc_poll, wsh_carriers wc_rsh
10014 WHERE rsl.po_header_id = p_source_header_id
10015 AND rsl.po_line_location_id = p_source_line_id
10016 AND rsl.shipment_line_id = p_source_line_detail_id
10017 AND poll.po_header_id = rsl.po_header_id
10018 AND poll.po_line_id = rsl.po_line_id
10019 AND poll.line_location_id = rsl.po_line_location_id
10020 AND rsl.shipment_header_id = rsh.shipment_header_id
10021 AND rsh.shipment_num IS NOT NULL
10022 AND rsh.receipt_source_code = 'VENDOR'
10023 AND rsh.asn_type IN ('ASN', 'ASBN')
10024 AND rsl.po_header_id = wdd.source_header_id (+)
10025 AND rsl.po_line_id = wdd.source_line_id (+)
10026 AND rsl.po_line_location_id = wdd.po_shipment_line_id (+)
10027 AND rsl.shipment_line_id = wdd.rcv_shipment_line_id (+)
10028 AND 'PO' = wdd.source_code (+)
10029 AND 'I' = wdd.line_direction (+)
10030 AND 'L' <> wdd.released_status (+)
10031 AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
10032 AND wda.delivery_id = wnd.delivery_id (+)
10033 AND wnd.delivery_id = wdl.delivery_id (+)
10034 AND (wdl.sequence_number IS NULL OR
10035 wdl.sequence_number = (SELECT MIN(sequence_number)
10036 FROM wsh_delivery_legs wdl_first_leg
10037 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
10038 AND wdl.drop_off_stop_id = wts.stop_id (+)
10039 AND wts.trip_id = wt.trip_id (+)
10040 AND wnd.ship_method_code = wcs_wnd.ship_method_code (+)
10041 AND wdd.ship_method_code = wcs_wdd.ship_method_code (+)
10042 AND poll.ship_via_lookup_code = wc_poll.freight_code (+)
10043 AND rsh.freight_carrier_code = wc_rsh.freight_code (+);
10044
10045
10046 -- Cursor to retrieve the trip stop id, carrier id, and expected receipt time
10047 -- (without considering dock appointments) for an Internal Requisition supply line.
10048 -- For Internal Req supply lines, reservations will store the Req header ID, Req line ID,
10049 -- and NULL as the source header ID, line ID, and line detail ID respectively.
10050 -- For release R12, since reservations for Internal Requisitions will only be at the
10051 -- Req header and line level, there can be multiple shipments tied to a given reservation.
10052 -- Ideally reservations should also be at the shipment line level for Internal Reqs that
10053 -- have shipped. Due to this limitation, when determining the expected receipt time,
10054 -- just use the earliest expected_receipt_date. There can be multiple records returned
10055 -- from this cursor if multiple shipment lines for the Internal Req exist.
10056 -- NOTE REGARDING INBOUND TRIPS:
10057 -- Currently, when an Inbound Trip is created, the trip has a planned arrival date
10058 -- set to be the last accept date for the inbound supply. When a shipment is created,
10059 -- the planned arrival date of the trip does not get updated. Thus the expected
10060 -- receipt date returned from this cursor is not the most accurate until the issue
10061 -- with trips is resolved.
10062 CURSOR intreq_rec_cursor IS
10063 SELECT prl.destination_organization_id AS organization_id,
10064 wts.stop_id AS trip_stop_id,
10065 NVL(wt.carrier_id,
10066 NVL(NVL(wnd.carrier_id, wcs_wnd.carrier_id),
10067 NVL(NVL(wdd.carrier_id, wcs_wdd.carrier_id),
10068 NVL(NVL(wc_ool.carrier_id, wcs_ool.carrier_id),
10069 NVL(wc_rsh.carrier_id,
10070 wcs_prl.carrier_id))))) AS carrier_id,
10071 NVL(wts.planned_arrival_date,
10072 NVL(NVL(rsh.expected_receipt_date, rsh.shipped_date),
10073 prl.need_by_date)) AS expected_receipt_date
10074 FROM po_requisition_lines_all prl, rcv_shipment_lines rsl, rcv_shipment_headers rsh,
10075 oe_order_lines_all ool, wsh_delivery_details wdd,
10076 wsh_delivery_assignments_v wda, wsh_new_deliveries wnd, wsh_delivery_legs wdl,
10077 wsh_trip_stops wts, wsh_trips wt, wsh_carrier_services wcs_wnd,
10078 wsh_carrier_services wcs_wdd, wsh_carrier_services wcs_ool,
10079 wsh_carriers wc_ool, wsh_carriers wc_rsh, wsh_carrier_services wcs_prl
10080 WHERE prl.requisition_header_id = p_source_header_id
10081 AND prl.requisition_line_id = p_source_line_id
10082 AND prl.source_type_code = 'INVENTORY'
10083 AND NVL(prl.cancel_flag, 'N') = 'N'
10084 AND prl.requisition_line_id = rsl.requisition_line_id (+)
10085 AND rsl.shipment_header_id = rsh.shipment_header_id (+)
10086 AND 10 = ool.order_source_id (+) -- Internal Order source type
10087 AND prl.requisition_header_id = ool.source_document_id (+)
10088 AND prl.requisition_line_id = ool.source_document_line_id (+)
10089 AND prl.item_id = ool.inventory_item_id (+)
10090 AND ool.header_id = wdd.source_header_id (+)
10091 AND ool.line_id = wdd.source_line_id (+)
10092 AND 'OE' = wdd.source_code (+)
10093 AND 'IO' = wdd.line_direction (+)
10094 AND 'L' <> wdd.released_status (+)
10095 AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
10096 AND wda.delivery_id = wnd.delivery_id (+)
10097 AND wnd.delivery_id = wdl.delivery_id (+)
10098 AND (wdl.sequence_number IS NULL OR
10099 wdl.sequence_number = (SELECT MIN(sequence_number)
10100 FROM wsh_delivery_legs wdl_first_leg
10101 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
10102 AND wdl.drop_off_stop_id = wts.stop_id (+)
10103 AND wts.trip_id = wt.trip_id (+)
10104 AND wnd.ship_method_code = wcs_wnd.ship_method_code (+)
10105 AND wdd.ship_method_code = wcs_wdd.ship_method_code (+)
10106 AND ool.shipping_method_code = wcs_ool.ship_method_code (+)
10107 AND ool.freight_carrier_code = wc_ool.freight_code (+)
10108 AND rsh.freight_carrier_code = wc_rsh.freight_code (+)
10109 AND prl.ship_method = wcs_prl.ship_method_code (+)
10110 ORDER BY expected_receipt_date ASC;
10111
10112
10113 -- Cursor to retrieve the trip stop id, carrier id, and expected receipt time
10114 -- (without considering dock appointments) for an In Transit Shipment supply line.
10115 -- For In Transit Shipment supply lines, reservations will store the RCV shipment header ID,
10116 -- RCV shipment line ID and NULL as the source header ID, line ID, and line detail ID
10117 -- respectively.
10118 CURSOR intship_rec_cursor IS
10119 SELECT rsl.to_organization_id AS organization_id,
10120 NULL AS trip_stop_id,
10121 wc_rsh.carrier_id as carrier_id,
10122 NVL(rsh.expected_receipt_date,
10123 NVL(rsh.shipped_date + NVL(mism.intransit_time, 0),
10124 rsh.shipped_date)) AS expected_receipt_date
10125 FROM rcv_shipment_lines rsl, rcv_shipment_headers rsh,
10126 wsh_carriers wc_rsh, mtl_interorg_ship_methods mism
10127 WHERE rsl.shipment_header_id = p_source_header_id
10128 AND rsl.shipment_line_id = p_source_line_id
10129 AND rsl.shipment_header_id = rsh.shipment_header_id
10130 AND rsh.shipment_num IS NOT NULL
10131 AND rsh.receipt_source_code = 'INVENTORY'
10132 AND rsh.freight_carrier_code = wc_rsh.freight_code (+)
10133 AND rsl.from_organization_id = mism.from_organization_id (+)
10134 AND rsl.to_organization_id = mism.to_organization_id (+)
10135 AND 1 = mism.default_flag (+);
10136
10137 -- Variables to retrieve the values from the source line cursors
10138 l_organization_id NUMBER;
10139 l_trip_stop_id NUMBER;
10140 l_carrier_id NUMBER;
10141 l_expected_date DATE;
10142
10143 -- Variables for calling the dock appointment API
10144 l_dock_appt_list WMS_DOCK_APPOINTMENTS_PUB.dock_appt_tb_tp;
10145
10146 -- Variables to loop through all dock appointments returned to find the one
10147 -- closest to the expected receipt/ship time.
10148 l_dock_schedule_method NUMBER;
10149 l_dock_start_time DATE;
10150 l_dock_mean_time DATE;
10151 l_dock_end_time DATE;
10152 l_dock_appt_time DATE;
10153 l_current_dock_appt_time DATE;
10154
10155 BEGIN
10156 IF (l_debug = 1) THEN
10157 print_debug('***Calling Get_Expected_Time with the following parameters***');
10158 print_debug('Package Version: ==========> ' || g_pkg_version);
10159 print_debug('p_source_type_id: =========> ' || p_source_type_id);
10160 print_debug('p_source_header_id: =======> ' || p_source_header_id);
10161 print_debug('p_source_line_id: =========> ' || p_source_line_id);
10162 print_debug('p_source_line_detail_id: ==> ' || p_source_line_detail_id);
10163 print_debug('p_supply_or_demand: =======> ' || p_supply_or_demand);
10164 print_debug('p_crossdock_criterion_id: => ' || p_crossdock_criterion_id);
10165 END IF;
10166
10167 -- Set the savepoint
10168 SAVEPOINT Get_Expected_Time_sp;
10169 l_progress := '10';
10170
10171 -- Initialize message list to clear any existing messages
10172 fnd_msg_pub.initialize;
10173 l_progress := '20';
10174
10175 -- Initialize API return status to success
10176 x_return_status := fnd_api.g_ret_sts_success;
10177 l_progress := '30';
10178
10179 -- Validate p_supply_or_demand
10180 -- {{
10181 -- Make sure API errors out if input variable p_supply_or_demand is not valid. }}
10182 IF (p_supply_or_demand NOT IN (G_SRC_TYPE_SUP, G_SRC_TYPE_DEM)) THEN
10183 IF (l_debug = 1) THEN
10184 print_debug('Invalid value for p_supply_or_demand: ' || p_supply_or_demand);
10185 END IF;
10186 RAISE fnd_api.g_exc_unexpected_error;
10187 END IF;
10188 l_progress := '40';
10189
10190 -- Validate that source type matches supply or demand
10191 IF (p_supply_or_demand = G_SRC_TYPE_SUP) THEN
10192 -- Check that source type is a valid supply source
10193 -- {{
10194 -- Make sure API errors out if supply type passed in is not valid. }}
10195 IF (p_source_type_id NOT IN (1, 7, 25, 26)) THEN
10196 IF (l_debug = 1) THEN
10197 print_debug('Invalid supply source type: ' || p_source_type_id);
10198 END IF;
10199 RAISE fnd_api.g_exc_unexpected_error;
10200 END IF;
10201 ELSIF (p_supply_or_demand = G_SRC_TYPE_DEM) THEN
10202 -- Check that source type is a valid demand source
10203 -- {{
10204 -- Make sure API errors out if demand type passed in is not valid. }}
10205 IF (p_source_type_id NOT IN (2, 8)) THEN
10206 IF (l_debug = 1) THEN
10207 print_debug('Invalid demand source type: ' || p_source_type_id);
10208 END IF;
10209 RAISE fnd_api.g_exc_unexpected_error;
10210 END IF;
10211 END IF;
10212 l_progress := '50';
10213
10214 -- If the crossdock criterion is passed, query and cache the value
10215 IF (p_crossdock_criterion_id IS NOT NULL) THEN
10216 IF (NOT set_crossdock_criteria(p_crossdock_criterion_id)) THEN
10217 IF (l_debug = 1) THEN
10218 print_debug('Unable to set the crossdock criterion: ' || p_crossdock_criterion_id);
10219 RAISE fnd_api.g_exc_unexpected_error;
10220 END IF;
10221 END IF;
10222
10223 -- Get the dock schedule method from the crossdock criterion
10224 -- {{
10225 -- If crossdock criterion is passed, make sure a valid non-null value for
10226 -- the dock schedule method is retrieved. }}
10227 IF (p_supply_or_demand = G_SRC_TYPE_SUP) THEN
10228 l_dock_schedule_method :=
10229 g_crossdock_criteria_tb(p_crossdock_criterion_id).supply_schedule_method;
10230 ELSIF (p_supply_or_demand = G_SRC_TYPE_DEM) THEN
10231 l_dock_schedule_method :=
10232 g_crossdock_criteria_tb(p_crossdock_criterion_id).demand_schedule_method;
10233 END IF;
10234 IF (l_debug = 1) THEN
10235 print_debug('Dock Schedule Method: ' || l_dock_schedule_method);
10236 END IF;
10237 END IF;
10238 l_progress := '60';
10239 -- End of validations and initializations
10240
10241
10242 -- Call the custom logic first to see if the API is implemented or not
10243 WMS_XDOCK_CUSTOM_APIS_PUB.Get_Expected_Time
10244 (p_source_type_id => p_source_type_id,
10245 p_source_header_id => p_source_header_id,
10246 p_source_line_id => p_source_line_id,
10247 p_source_line_detail_id => p_source_line_detail_id,
10248 p_supply_or_demand => p_supply_or_demand,
10249 p_crossdock_criterion_id => p_crossdock_criterion_id,
10250 p_dock_schedule_method => l_dock_schedule_method,
10251 x_return_status => x_return_status,
10252 x_msg_count => x_msg_count,
10253 x_msg_data => x_msg_data,
10254 x_api_is_implemented => l_api_is_implemented,
10255 x_dock_start_time => x_dock_start_time,
10256 x_dock_mean_time => x_dock_mean_time,
10257 x_dock_end_time => x_dock_end_time,
10258 x_expected_time => x_expected_time);
10259
10260 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10261 IF (l_debug = 1) THEN
10262 print_debug('Success returned from Custom Get_Expected_Time API');
10263 END IF;
10264 ELSE
10265 IF (l_debug = 1) THEN
10266 print_debug('Failure returned from Custom Get_Expected_Time API');
10267 END IF;
10268 RAISE fnd_api.g_exc_error;
10269 END IF;
10270
10271 -- If the custom API is implemented, just use the values retrieved from there.
10272 -- Skip all further processing and logic in this API.
10273 IF (l_api_is_implemented) THEN
10274 IF (l_debug = 1) THEN
10275 print_debug('Custom API is implemented so using custom logic to get expected time');
10276 END IF;
10277 GOTO custom_logic_used;
10278 ELSE
10279 IF (l_debug = 1) THEN
10280 print_debug('Custom API is not implemented so using default logic to get expected time');
10281 END IF;
10282 END IF;
10283
10284 -- Check the source type to decide which cursor to open to retrieve the
10285 -- trip stop, carrier, and non-dock appointment derived expected receipt/ship time.
10286 IF (p_source_type_id IN (2, 8)) THEN
10287 -- Sales Order or Internal Order
10288 -- {{
10289 -- Get the expected time for a sales order and internal order demand. }}
10290 OPEN wdd_rec_cursor;
10291 FETCH wdd_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id, l_expected_date;
10292 IF (wdd_rec_cursor%NOTFOUND) THEN
10293 IF (l_debug = 1) THEN
10294 print_debug('WDD cursor did not return any records!');
10295 END IF;
10296 CLOSE wdd_rec_cursor;
10297 RAISE fnd_api.g_exc_unexpected_error;
10298 END IF;
10299 CLOSE wdd_rec_cursor;
10300 ELSIF (p_source_type_id = 1) THEN
10301 -- Purchase Order
10302 -- {{
10303 -- Get the expected time for a PO. }}
10304 OPEN po_rec_cursor;
10305 FETCH po_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id, l_expected_date;
10306 IF (po_rec_cursor%NOTFOUND) THEN
10307 IF (l_debug = 1) THEN
10308 print_debug('PO cursor did not return any records!');
10309 END IF;
10310 CLOSE po_rec_cursor;
10311 RAISE fnd_api.g_exc_unexpected_error;
10312 END IF;
10313 CLOSE po_rec_cursor;
10314 ELSIF (p_source_type_id = 25) THEN
10315 -- ASN
10316 -- {{
10317 -- Get the expected time for an ASN. }}
10318 OPEN asn_rec_cursor;
10319 FETCH asn_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id, l_expected_date;
10320 IF (asn_rec_cursor%NOTFOUND) THEN
10321 IF (l_debug = 1) THEN
10322 print_debug('ASN cursor did not return any records!');
10323 END IF;
10324 CLOSE asn_rec_cursor;
10325 RAISE fnd_api.g_exc_unexpected_error;
10326 END IF;
10327 CLOSE asn_rec_cursor;
10328 ELSIF (p_source_type_id = 7) THEN
10329 -- Internal Requisition
10330 -- {{
10331 -- Get the expected time for an Internal Req. }}
10332 OPEN intreq_rec_cursor;
10333 FETCH intreq_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id, l_expected_date;
10334 IF (intreq_rec_cursor%NOTFOUND) THEN
10335 IF (l_debug = 1) THEN
10336 print_debug('INTREQ cursor did not return any records!');
10337 END IF;
10338 CLOSE intreq_rec_cursor;
10339 RAISE fnd_api.g_exc_unexpected_error;
10340 END IF;
10341 CLOSE intreq_rec_cursor;
10342 ELSIF (p_source_type_id = 26) THEN
10343 -- In Transit Shipment
10344 -- {{
10345 -- Get the expected time for an In Transit Shipment. }}
10346 OPEN intship_rec_cursor;
10347 FETCH intship_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id, l_expected_date;
10348 IF (intship_rec_cursor%NOTFOUND) THEN
10349 IF (l_debug = 1) THEN
10350 print_debug('INTSHIP cursor did not return any records!');
10351 END IF;
10352 CLOSE intship_rec_cursor;
10353 RAISE fnd_api.g_exc_unexpected_error;
10354 END IF;
10355 CLOSE intship_rec_cursor;
10356 END IF;
10357 l_progress := '70';
10358
10359 IF (l_debug = 1) THEN
10360 print_debug('Successfully retrieved data from cursor');
10361 print_debug('Organization ID: => ' || l_organization_id);
10362 print_debug('Trip Stop ID: ====> ' || l_trip_stop_id);
10363 print_debug('Carrier ID: ======> ' || l_carrier_id);
10364 print_debug('Expected Date: ===> ' || TO_CHAR(l_expected_date, 'DD-MON-YYYY HH24:MI:SS'));
10365 END IF;
10366 l_progress := '80';
10367
10368 -- If a trip stop is present, query for dock appointments associated with the trip stop.
10369 -- If a trip stop is passed to this API, the start and end date parameters are ignored
10370 -- and the first dock appointment associated with the trip stop is returned. This will
10371 -- return at most one dock appointment in the output variable table x_dock_appt_list.
10372 -- CORRECTION TO THE ABOVE:
10373 -- The dock appointment API, even if a trip stop is passed does take the p_start_date into
10374 -- account. Since dock appointment statuses do not exist yet, this API will only look for
10375 -- dock appointments tied to the trip stop that are >= p_start_date. This is done so we do
10376 -- not pick up older dock appointments that have already passed. (Though that should not be
10377 -- an issue for dock appointments tied to trip stops). Thus use SYSDATE for p_start_date
10378 -- instead of l_expected_date.
10379 -- {{
10380 -- Test for cases both with and without a dock appointment tied to an existing trip stop. }}
10381 IF (l_trip_stop_id IS NOT NULL) THEN
10382 IF (l_debug = 1) THEN
10383 print_debug('Call the get_dock_appointment_range API for a trip stop');
10384 END IF;
10385 l_progress := '90';
10386
10387 wms_dock_appointments_pub.get_dock_appointment_range
10388 (p_api_version => 1.0,
10389 p_init_msg_list => fnd_api.g_false,
10390 x_return_status => x_return_status,
10391 x_msg_count => x_msg_count,
10392 x_msg_data => x_msg_data,
10393 x_dock_appt_list => l_dock_appt_list,
10394 p_organization_id => l_organization_id,
10395 p_start_date => Trunc(Sysdate), --l_expected_date,
10396 p_end_date => l_expected_date,
10397 p_appointment_type => p_supply_or_demand,
10398 p_supplier_id => NULL,
10399 p_supplier_site_id => NULL,
10400 p_customer_id => NULL,
10401 p_customer_site_id => NULL,
10402 p_carrier_code => NULL,
10403 p_carrier_id => NULL,
10404 p_trip_stop_id => l_trip_stop_id,
10405 p_waybill_number => NULL,
10406 p_bill_of_lading => NULL,
10407 p_master_bol => NULL);
10408
10409 IF (l_debug = 1) THEN
10410 print_debug('Finished calling the get_dock_appointment_range API');
10411 END IF;
10412 l_progress := '100';
10413
10414 -- Check to see if the get_dock_appointment_range API returned successfully
10415 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10416 IF (l_debug = 1) THEN
10417 print_debug('Success returned from get_dock_appointment_range API');
10418 END IF;
10419 ELSE
10420 IF (l_debug = 1) THEN
10421 print_debug('Failure returned from get_dock_appointment_range API');
10422 END IF;
10423 x_return_status := fnd_api.g_ret_sts_success;
10424 -- do not thrown an error but just go to the next way to calculate time
10425 --FND_MESSAGE.SET_NAME('WMS', 'WMS_TD_MO_ERROR');
10426 --FND_MSG_PUB.ADD;
10427 --RAISE fnd_api.g_exc_error;
10428 END IF;
10429 l_progress := '110';
10430 END IF;
10431
10432 -- If a dock appointment has not been found yet and a carrier ID is present,
10433 -- query for dock appointments associated with the carrier. For the start and end dates,
10434 -- we will use the date on the variable l_expected_date (sans time information if present)
10435 -- along with the times of 12AM midnight and 11:59:59PM as the start and end date.
10436 -- This will return a list of valid dock appointments (multiple appointments are possible).
10437 -- {{
10438 -- Test for cases both with and without a dock appointment tied to an existing carrier. }}
10439 -- {{
10440 -- Test for cases where multiple dock appointments exist for a given carrier. }}
10441 IF (l_dock_appt_list.COUNT = 0 AND l_carrier_id IS NOT NULL) THEN
10442 IF (l_debug = 1) THEN
10443 print_debug('Call the get_dock_appointment_range API for a carrier');
10444 END IF;
10445 l_progress := '120';
10446
10447 wms_dock_appointments_pub.get_dock_appointment_range
10448 (p_api_version => 1.0,
10449 p_init_msg_list => fnd_api.g_false,
10450 x_return_status => x_return_status,
10451 x_msg_count => x_msg_count,
10452 x_msg_data => x_msg_data,
10453 x_dock_appt_list => l_dock_appt_list,
10454 p_organization_id => l_organization_id,
10455 p_start_date => TRUNC(l_expected_date),
10456 p_end_date => TO_DATE(TO_CHAR(TRUNC(l_expected_date), 'DD-MON-YYYY') ||
10457 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS'),
10458 p_appointment_type => p_supply_or_demand,
10459 p_supplier_id => NULL,
10460 p_supplier_site_id => NULL,
10461 p_customer_id => NULL,
10462 p_customer_site_id => NULL,
10463 p_carrier_code => NULL,
10464 p_carrier_id => l_carrier_id,
10465 p_trip_stop_id => NULL,
10466 p_waybill_number => NULL,
10467 p_bill_of_lading => NULL,
10468 p_master_bol => NULL);
10469
10470 IF (l_debug = 1) THEN
10471 print_debug('Finished calling the get_dock_appointment_range API');
10472 END IF;
10473 l_progress := '130';
10474
10475 -- Check to see if the get_dock_appointment_range API returned successfully
10476 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10477 IF (l_debug = 1) THEN
10478 print_debug('Success returned from get_dock_appointment_range API');
10479 END IF;
10480 ELSE
10481 IF (l_debug = 1) THEN
10482 print_debug('Failure returned from get_dock_appointment_range API');
10483 END IF;
10484 x_return_status := fnd_api.g_ret_sts_success;
10485 -- do not thrown an error but just go to the next way to calculate time
10486 --FND_MESSAGE.SET_NAME('WMS', 'WMS_TD_MO_ERROR');
10487 --FND_MSG_PUB.ADD;
10488 --RAISE fnd_api.g_exc_error;
10489 END IF;
10490 l_progress := '140';
10491 END IF;
10492
10493 IF (l_debug = 1) THEN
10494 print_debug('Number of dock appointments found: ' || l_dock_appt_list.COUNT);
10495 END IF;
10496 l_progress := '150';
10497
10498 -- See if any dock appointments were found. If multiple dock appointments exist,
10499 -- get the one closest to the expected receipt/ship date
10500 IF (l_dock_appt_list.COUNT > 0) THEN
10501 -- Loop through all available dock appointments
10502 -- {{
10503 -- For multiple dock appointments, make sure the 'closest' one is correctly selected. }}
10504 FOR i IN l_dock_appt_list.FIRST .. l_dock_appt_list.LAST LOOP
10505 IF (i = l_dock_appt_list.FIRST) THEN
10506 -- First dock appointment found
10507 l_dock_start_time := l_dock_appt_list(i).start_time;
10508 l_dock_end_time := l_dock_appt_list(i).end_time;
10509 l_dock_mean_time := (l_dock_end_time - l_dock_start_time)/2 + l_dock_start_time;
10510
10511 -- Based on the dock schedule method (if present) calculate a single
10512 -- dock appointment time based on the start and end time. If multiple dock
10513 -- appointments exist, this value will be compared with the expected receipt/ship
10514 -- date (non-dock appointment) and the closest dock appointment time will be used.
10515 IF (l_dock_schedule_method IS NULL OR l_dock_schedule_method = G_APPT_MEAN_TIME) THEN
10516 l_dock_appt_time := l_dock_mean_time;
10517 ELSIF (l_dock_schedule_method = G_APPT_START_TIME) THEN
10518 l_dock_appt_time := l_dock_start_time;
10519 ELSIF (l_dock_schedule_method = G_APPT_END_TIME) THEN
10520 l_dock_appt_time := l_dock_end_time;
10521 END IF;
10522 IF (l_debug = 1) THEN
10523 print_debug('Current closest dock appt time: ' ||
10524 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
10525 END IF;
10526 l_progress := '160';
10527 ELSE
10528 -- Calculate the current dock appointment time and compare it to the current
10529 -- best time to see if this one is even closer to the expected receipt/ship date.
10530 IF (l_dock_schedule_method IS NULL OR l_dock_schedule_method = G_APPT_MEAN_TIME) THEN
10531 l_current_dock_appt_time := (l_dock_appt_list(i).end_time -
10532 l_dock_appt_list(i).start_time)/2
10533 + l_dock_appt_list(i).start_time;
10534 ELSIF (l_dock_schedule_method = G_APPT_START_TIME) THEN
10535 l_current_dock_appt_time := l_dock_appt_list(i).start_time;
10536 ELSIF (l_dock_schedule_method = G_APPT_END_TIME) THEN
10537 l_current_dock_appt_time := l_dock_appt_list(i).end_time;
10538 END IF;
10539
10540 -- If the dock appointment time is closer to the expected receipt/ship date compared
10541 -- to the current best time, update the best dock appointment variables to
10542 -- point to the current dock appointment.
10543 IF (abs(l_current_dock_appt_time - l_expected_date) <
10544 abs(l_dock_appt_time - l_expected_date)) THEN
10545 l_dock_start_time := l_dock_appt_list(i).start_time;
10546 l_dock_end_time := l_dock_appt_list(i).end_time;
10547 l_dock_mean_time := (l_dock_end_time - l_dock_start_time)/2 + l_dock_start_time;
10548 l_dock_appt_time := l_current_dock_appt_time;
10549 IF (l_debug = 1) THEN
10550 print_debug('Closer dock appt time found: ' ||
10551 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
10552 END IF;
10553 END IF;
10554 l_progress := '170';
10555
10556 END IF;
10557 END LOOP;
10558
10559 IF (l_debug = 1) THEN
10560 print_debug('Closest dock appt start time: => ' ||
10561 TO_CHAR(l_dock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
10562 print_debug('Closest dock appt end time: ===> ' ||
10563 TO_CHAR(l_dock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
10564 print_debug('Closest dock appt mean time: ==> ' ||
10565 TO_CHAR(l_dock_mean_time, 'DD-MON-YYYY HH24:MI:SS'));
10566 print_debug('Closest dock appt time: =======> ' ||
10567 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
10568 END IF;
10569 l_progress := '180';
10570
10571 -- We have now found the closest dock appointment time to the expected time
10572 x_dock_start_time := l_dock_start_time;
10573 x_dock_mean_time := l_dock_mean_time;
10574 x_dock_end_time := l_dock_end_time;
10575 IF (p_crossdock_criterion_id IS NOT NULL) THEN
10576 x_expected_time := l_dock_appt_time;
10577 ELSE
10578 -- If a crossdock criterion is not passed, let the caller decide how to determine
10579 -- a single expected time based on the dock appointment start and end time.
10580 x_expected_time := NULL;
10581 END IF;
10582 l_progress := '190';
10583 END IF; -- End of dock appointments found
10584
10585 -- If a dock appointment was not found, just use the expected receipt/ship date
10586 -- retrieved from the cursors as the expected time.
10587 -- {{
10588 -- Ensure that the expected time calculated not based on dock appointments is returned
10589 -- in case no dock appointments exist for the inputted demand/supply line. }}
10590 IF (l_dock_appt_list.COUNT = 0) THEN
10591 x_dock_start_time := NULL;
10592 x_dock_mean_time := NULL;
10593 x_dock_end_time := NULL;
10594 x_expected_time := l_expected_date;
10595 END IF;
10596 l_progress := '200';
10597
10598 IF (l_debug = 1) THEN
10599 print_debug('Dock start time: => ' || TO_CHAR(x_dock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
10600 print_debug('Dock mean time: ==> ' || TO_CHAR(x_dock_mean_time, 'DD-MON-YYYY HH24:MI:SS'));
10601 print_debug('Dock end time: ===> ' || TO_CHAR(x_dock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
10602 print_debug('Expected time: ===> ' || TO_CHAR(x_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
10603 END IF;
10604
10605 <<custom_logic_used>>
10606 IF (l_debug = 1) THEN
10607 print_debug('***End of Get_Expected_Time***');
10608 END IF;
10609
10610 EXCEPTION
10611 WHEN FND_API.G_EXC_ERROR THEN
10612 ROLLBACK TO Get_Expected_Time_sp;
10613 x_return_status := fnd_api.g_ret_sts_error;
10614 fnd_msg_pub.count_and_get(p_count => x_msg_count,
10615 p_data => x_msg_data);
10616 IF (l_debug = 1) THEN
10617 print_debug('Exiting Get_Expected_Time - Execution error: ' ||
10618 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
10619 END IF;
10620
10621 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
10622 ROLLBACK TO Get_Expected_Time_sp;
10623 x_return_status := fnd_api.g_ret_sts_unexp_error;
10624 fnd_msg_pub.count_and_get(p_count => x_msg_count,
10625 p_data => x_msg_data);
10626 IF (l_debug = 1) THEN
10627 print_debug('Exiting Get_Expected_Time - Unexpected error: ' ||
10628 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
10629 END IF;
10630
10631 WHEN OTHERS THEN
10632 ROLLBACK TO Get_Expected_Time_sp;
10633 x_return_status := fnd_api.g_ret_sts_unexp_error;
10634 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
10635 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
10636 END IF;
10637 fnd_msg_pub.count_and_get(p_count => x_msg_count,
10638 p_data => x_msg_data);
10639 IF (l_debug = 1) THEN
10640 print_debug('Exiting Get_Expected_Time - Others exception: ' ||
10641 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
10642 END IF;
10643
10644 END Get_Expected_Time;
10645 -- {{ }}
10646 -- {{******************** End Get_Expected_Time ********************}}
10647 -- {{ }}
10648
10649
10650 -- {{ }}
10651 -- {{******************** Procedure Get_Expected_Delivery_Time ********************}}
10652 PROCEDURE Get_Expected_Delivery_Time
10653 (p_delivery_id IN NUMBER,
10654 p_crossdock_criterion_id IN NUMBER,
10655 x_return_status OUT NOCOPY VARCHAR2,
10656 x_msg_count OUT NOCOPY NUMBER,
10657 x_msg_data OUT NOCOPY VARCHAR2,
10658 x_dock_appointment_id OUT NOCOPY NUMBER,
10659 x_dock_start_time OUT NOCOPY DATE,
10660 x_dock_end_time OUT NOCOPY DATE,
10661 x_expected_time OUT NOCOPY DATE)
10662 IS
10663 l_api_name CONSTANT VARCHAR2(30) := 'Get_Expected_Delivery_Time';
10664 l_progress VARCHAR2(10);
10665 l_debug NUMBER := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
10666
10667 -- This variable is used to indicate if the custom API was used to determine
10668 -- the expected time values.
10669 l_api_is_implemented BOOLEAN;
10670
10671 -- Variable to store the dock schedule method for outbound demand lines
10672 -- from the crossdock criterion entered
10673 l_dock_schedule_method NUMBER;
10674
10675 -- Cursor to retrieve the trip stop id, carrier id, min expected ship date and max
10676 -- expected ship date (without considering dock appointments) for a given delivery.
10677 -- The carrier and expected ship dates come from the set of outbound WDD/OOL records
10678 -- already assigned to the delivery.
10679 CURSOR delivery_rec_cursor IS
10680 SELECT wnd.organization_id AS organization_id,
10681 wts.stop_id AS trip_stop_id,
10682 MIN(NVL(wt.carrier_id,
10683 NVL(NVL(wnd.carrier_id, wcs_wnd.carrier_id),
10684 NVL(NVL(wdd.carrier_id, wcs_wdd.carrier_id),
10685 NVL(wc_ool.carrier_id, wcs_ool.carrier_id))))) AS carrier_id,
10686 MIN(NVL(wts.planned_departure_date,
10687 NVL(wdd.date_scheduled,
10688 NVL(ool.schedule_ship_date, ool.promise_date)))) AS min_expected_ship_date,
10689 MAX(NVL(wts.planned_departure_date,
10690 NVL(wdd.date_scheduled,
10691 NVL(ool.schedule_ship_date, ool.promise_date)))) AS max_expected_ship_date
10692 FROM wsh_new_deliveries wnd, wsh_delivery_details wdd, wsh_delivery_assignments_v wda,
10693 wsh_delivery_legs wdl, wsh_trip_stops wts, wsh_trips wt, oe_order_lines_all ool,
10694 wsh_carrier_services wcs_wnd, wsh_carrier_services wcs_wdd,
10695 wsh_carrier_services wcs_ool, wsh_carriers wc_ool
10696 WHERE wnd.delivery_id = p_delivery_id
10697 AND wnd.shipment_direction = 'O'
10698 AND wnd.delivery_id = wda.delivery_id (+)
10699 AND wda.delivery_detail_id = wdd.delivery_detail_id (+)
10700 AND wdd.source_line_id = ool.line_id (+)
10701 AND wnd.delivery_id = wdl.delivery_id (+)
10702 AND (wdl.sequence_number IS NULL OR
10703 wdl.sequence_number = (SELECT MIN(sequence_number)
10704 FROM wsh_delivery_legs wdl_first_leg
10705 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
10706 AND wdl.pick_up_stop_id = wts.stop_id (+)
10707 AND wts.trip_id = wt.trip_id (+)
10708 AND wnd.ship_method_code = wcs_wnd.ship_method_code (+)
10709 AND wdd.ship_method_code = wcs_wdd.ship_method_code (+)
10710 AND ool.shipping_method_code = wcs_ool.ship_method_code (+)
10711 AND ool.freight_carrier_code = wc_ool.freight_code (+)
10712 GROUP BY wnd.organization_id, wnd.delivery_id, wts.stop_id;
10713
10714 -- Variables to retrieve the values from the delivery record cursor
10715 l_organization_id NUMBER;
10716 l_trip_stop_id NUMBER;
10717 l_carrier_id NUMBER;
10718 l_min_expected_date DATE;
10719 l_max_expected_date DATE;
10720 l_null_dates_retrieved BOOLEAN;
10721
10722 -- Variables for calling the dock appointment API
10723 l_dock_appt_list WMS_DOCK_APPOINTMENTS_PUB.dock_appt_tb_tp;
10724
10725 -- Variables to loop through all dock appointments returned to find the one
10726 -- closest to the expected receipt/ship time.
10727 l_dock_appointment_id NUMBER;
10728 l_dock_start_time DATE;
10729 l_dock_end_time DATE;
10730 l_dock_appt_time DATE;
10731 l_current_dock_appt_time DATE;
10732
10733 BEGIN
10734 IF (l_debug = 1) THEN
10735 print_debug('***Calling Get_Expected_Delivery_Time with the following parameters***');
10736 print_debug('Package Version: ==========> ' || g_pkg_version);
10737 print_debug('p_delivery_id: ============> ' || p_delivery_id);
10738 print_debug('p_crossdock_criterion_id: => ' || p_crossdock_criterion_id);
10739 END IF;
10740
10741 -- Set the savepoint
10742 SAVEPOINT Get_Expected_Delivery_Time_sp;
10743 l_progress := '10';
10744
10745 -- Initialize message list to clear any existing messages
10746 fnd_msg_pub.initialize;
10747 l_progress := '20';
10748
10749 -- Initialize API return status to success
10750 x_return_status := fnd_api.g_ret_sts_success;
10751 l_progress := '30';
10752
10753 -- Query and cache the crossdock criterion record
10754 IF (NOT set_crossdock_criteria(p_crossdock_criterion_id)) THEN
10755 IF (l_debug = 1) THEN
10756 print_debug('Unable to set the crossdock criterion: ' || p_crossdock_criterion_id);
10757 RAISE fnd_api.g_exc_unexpected_error;
10758 END IF;
10759 END IF;
10760 l_progress := '40';
10761
10762 -- No need to do the following validation since this can also be called for MOL lines that
10763 -- were Planned Crossdocked so the crossdock criterion there is of 'Planned' type.
10764 -- Validate that the crossdock criteria is of 'Opportunistic' type.
10765 /*IF (g_crossdock_criteria_tb(p_crossdock_criterion_id).criterion_type <> G_CRT_TYPE_OPP) THEN
10766 IF (l_debug = 1) THEN
10767 print_debug('Invalid crossdock criterion type: ' ||
10768 g_crossdock_criteria_tb(p_crossdock_criterion_id).criterion_type);
10769 END IF;
10770 RAISE fnd_api.g_exc_unexpected_error;
10771 END IF;*/
10772 l_progress := '50';
10773
10774 -- Get the dock schedule method from the crossdock criterion
10775 -- {{
10776 -- make sure a valid dock schedule method is retrieved from the crossdock criterion. }}
10777 l_dock_schedule_method :=
10778 g_crossdock_criteria_tb(p_crossdock_criterion_id).demand_schedule_method;
10779 IF (l_debug = 1) THEN
10780 print_debug('Dock Schedule Method: ' || l_dock_schedule_method);
10781 END IF;
10782 l_progress := '60';
10783 -- End of validations and initializations
10784
10785
10786 -- Call the custom logic first to see if the API is implemented or not
10787 WMS_XDOCK_CUSTOM_APIS_PUB.Get_Expected_Delivery_Time
10788 (p_delivery_id => p_delivery_id,
10789 p_crossdock_criterion_id => p_crossdock_criterion_id,
10790 p_dock_schedule_method => l_dock_schedule_method,
10791 x_return_status => x_return_status,
10792 x_msg_count => x_msg_count,
10793 x_msg_data => x_msg_data,
10794 x_api_is_implemented => l_api_is_implemented,
10795 x_dock_appointment_id => x_dock_appointment_id,
10796 x_dock_start_time => x_dock_start_time,
10797 x_dock_end_time => x_dock_end_time,
10798 x_expected_time => x_expected_time);
10799
10800 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10801 IF (l_debug = 1) THEN
10802 print_debug('Success returned from Custom Get_Expected_Delivery_Time API');
10803 END IF;
10804 ELSE
10805 IF (l_debug = 1) THEN
10806 print_debug('Failure returned from Custom Get_Expected_Delivery_Time API');
10807 END IF;
10808 RAISE fnd_api.g_exc_error;
10809 END IF;
10810
10811 -- If the custom API is implemented, just use the values retrieved from there.
10812 -- Skip all further processing and logic in this API.
10813 IF (l_api_is_implemented) THEN
10814 IF (l_debug = 1) THEN
10815 print_debug('Custom API is implemented so using custom logic to get expected time');
10816 END IF;
10817 GOTO custom_logic_used;
10818 ELSE
10819 IF (l_debug = 1) THEN
10820 print_debug('Custom API is not implemented so using default logic to get expected time');
10821 END IF;
10822 END IF;
10823
10824 -- Open the delivery record cursor to retrieve the trip stop, carrier and
10825 -- non-dock appointment derived min and max expected ship times.
10826 -- {{
10827 -- Make sure API errors out properly if delivery entered is invalid. }}
10828 OPEN delivery_rec_cursor;
10829 FETCH delivery_rec_cursor INTO l_organization_id, l_trip_stop_id, l_carrier_id,
10830 l_min_expected_date, l_max_expected_date;
10831 IF (delivery_rec_cursor%NOTFOUND) THEN
10832 IF (l_debug = 1) THEN
10833 print_debug('Delivery cursor did not return any records!');
10834 END IF;
10835 CLOSE delivery_rec_cursor;
10836 RAISE fnd_api.g_exc_unexpected_error;
10837 END IF;
10838 CLOSE delivery_rec_cursor;
10839 l_progress := '70';
10840
10841 IF (l_debug = 1) THEN
10842 print_debug('Successfully retrieved data from cursor');
10843 print_debug('Organization ID: ===> ' || l_organization_id);
10844 print_debug('Trip Stop ID: ======> ' || l_trip_stop_id);
10845 print_debug('Carrier ID: ========> ' || l_carrier_id);
10846 print_debug('Min Expected Date: => ' || TO_CHAR(l_min_expected_date, 'DD-MON-YYYY HH24:MI:SS'));
10847 print_debug('Max Expected Date: => ' || TO_CHAR(l_max_expected_date, 'DD-MON-YYYY HH24:MI:SS'));
10848 END IF;
10849 l_progress := '80';
10850
10851 -- If values were not returned for the MIN/MAX expected ship dates, just use SYSDATE
10852 -- with a time of 12:00AM for the start time and 11:59PM for the end time.
10853 -- Either both or none of the expected ship dates should be NULL. Set a BOOLEAN variable
10854 -- to indicate if NULL date values were retrieved from the cursor or not. This can occur
10855 -- if no WDD records are assigned to the delivery.
10856 -- {{
10857 -- Test for deliveries that do not have any WDD records assigned to them yet. }}
10858 -- {{
10859 -- For deliveries with WDD records already assigned to them, make sure the min and max
10860 -- expected dates are calculated correctly. }}
10861 IF (l_min_expected_date IS NULL) THEN
10862 l_null_dates_retrieved := TRUE;
10863 l_min_expected_date := TRUNC(SYSDATE);
10864 l_max_expected_date := TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'DD-MON-YYYY') ||
10865 ' 23:59:59', 'DD-MON-YYYY HH24:MI:SS');
10866 IF (l_debug = 1) THEN
10867 print_debug('Set the MIN/MAX expected dates to use SYSDATE due to NULL values');
10868 END IF;
10869 ELSE
10870 l_null_dates_retrieved := FALSE;
10871 END IF;
10872 l_progress := '85';
10873
10874 -- If a trip stop is present, query for dock appointments associated with the trip stop.
10875 -- If a trip stop is passed to this API, the start and end date parameters are ignored
10876 -- and the first dock appointment associated with the trip stop is returned. This will
10877 -- return at most one dock appointment in the output variable table x_dock_appt_list.
10878 -- CORRECTION TO THE ABOVE:
10879 -- The dock appointment API, even if a trip stop is passed does take the p_start_date into
10880 -- account. Since dock appointment statuses do not exist yet, this API will only look for
10881 -- dock appointments tied to the trip stop that are >= p_start_date. This is done so we do
10882 -- not pick up older dock appointments that have already passed. (Though that should not be
10883 -- an issue for dock appointments tied to trip stops). Thus use SYSDATE for p_start_date
10884 -- instead of l_min_expected_date.
10885 -- {{
10886 -- Get the expected time both with and without a trip stop tied to the delivery. }}
10887 IF (l_trip_stop_id IS NOT NULL) THEN
10888 IF (l_debug = 1) THEN
10889 print_debug('Call the get_dock_appointment_range API for a trip stop');
10890 END IF;
10891 l_progress := '90';
10892
10893 wms_dock_appointments_pub.get_dock_appointment_range
10894 (p_api_version => 1.0,
10895 p_init_msg_list => fnd_api.g_false,
10896 x_return_status => x_return_status,
10897 x_msg_count => x_msg_count,
10898 x_msg_data => x_msg_data,
10899 x_dock_appt_list => l_dock_appt_list,
10900 p_organization_id => l_organization_id,
10901 p_start_date => Trunc(Sysdate), --l_min_expected_date,
10902 p_end_date => l_max_expected_date,
10903 p_appointment_type => G_SRC_TYPE_DEM, -- Outbound Demand type
10904 p_supplier_id => NULL,
10905 p_supplier_site_id => NULL,
10906 p_customer_id => NULL,
10907 p_customer_site_id => NULL,
10908 p_carrier_code => NULL,
10909 p_carrier_id => NULL,
10910 p_trip_stop_id => l_trip_stop_id,
10911 p_waybill_number => NULL,
10912 p_bill_of_lading => NULL,
10913 p_master_bol => NULL);
10914
10915 IF (l_debug = 1) THEN
10916 print_debug('Finished calling the get_dock_appointment_range API');
10917 END IF;
10918 l_progress := '100';
10919
10920 -- Check to see if the get_dock_appointment_range API returned successfully
10921 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10922 IF (l_debug = 1) THEN
10923 print_debug('Success returned from get_dock_appointment_range API');
10924 END IF;
10925 ELSE
10926 IF (l_debug = 1) THEN
10927 print_debug('Failure returned from get_dock_appointment_range API');
10928 END IF;
10929 x_return_status := fnd_api.g_ret_sts_success;
10930 -- do not thrown an error but just go to the next way to calculate time
10931 --FND_MESSAGE.SET_NAME('WMS', 'WMS_TD_MO_ERROR');
10932 --FND_MSG_PUB.ADD;
10933 --RAISE fnd_api.g_exc_error;
10934 END IF;
10935 l_progress := '110';
10936 END IF;
10937
10938 -- If a dock appointment has not been found yet and a carrier ID is present,
10939 -- query for dock appointments associated with the carrier. For the start and end dates,
10940 -- use the MIN and MAX expected ship dates retrieved from the delivery record cursor.
10941 -- This will return a list of valid dock appointments (multiple appointments are possible).
10942 -- {{
10943 -- Get the expected delivery time both with and without a carrier tied to the delivery. }}
10944 -- {{
10945 -- Test for cases where multiple dock appointments are tied to the carrier. }}
10946 IF (l_dock_appt_list.COUNT = 0 AND l_carrier_id IS NOT NULL) THEN
10947 IF (l_debug = 1) THEN
10948 print_debug('Call the get_dock_appointment_range API for a carrier');
10949 END IF;
10950 l_progress := '120';
10951
10952 wms_dock_appointments_pub.get_dock_appointment_range
10953 (p_api_version => 1.0,
10954 p_init_msg_list => fnd_api.g_false,
10955 x_return_status => x_return_status,
10956 x_msg_count => x_msg_count,
10957 x_msg_data => x_msg_data,
10958 x_dock_appt_list => l_dock_appt_list,
10959 p_organization_id => l_organization_id,
10960 p_start_date => l_min_expected_date,
10961 p_end_date => l_max_expected_date,
10962 p_appointment_type => G_SRC_TYPE_DEM, -- Outbound Demand type
10963 p_supplier_id => NULL,
10964 p_supplier_site_id => NULL,
10965 p_customer_id => NULL,
10966 p_customer_site_id => NULL,
10967 p_carrier_code => NULL,
10968 p_carrier_id => l_carrier_id,
10969 p_trip_stop_id => NULL,
10970 p_waybill_number => NULL,
10971 p_bill_of_lading => NULL,
10972 p_master_bol => NULL);
10973
10974 IF (l_debug = 1) THEN
10975 print_debug('Finished calling the get_dock_appointment_range API');
10976 END IF;
10977 l_progress := '130';
10978
10979 -- Check to see if the get_dock_appointment_range API returned successfully
10980 IF (x_return_status = fnd_api.g_ret_sts_success) THEN
10981 IF (l_debug = 1) THEN
10982 print_debug('Success returned from get_dock_appointment_range API');
10983 END IF;
10984 ELSE
10985 IF (l_debug = 1) THEN
10986 print_debug('Failure returned from get_dock_appointment_range API');
10987 END IF;
10988 x_return_status := fnd_api.g_ret_sts_success;
10989 -- do not thrown an error but just go to the next way to calculate time
10990 --FND_MESSAGE.SET_NAME('WMS', 'WMS_TD_MO_ERROR');
10991 --FND_MSG_PUB.ADD;
10992 --RAISE fnd_api.g_exc_error;
10993 END IF;
10994 l_progress := '140';
10995 END IF;
10996
10997 IF (l_debug = 1) THEN
10998 print_debug('Number of dock appointments found: ' || l_dock_appt_list.COUNT);
10999 END IF;
11000 l_progress := '150';
11001
11002 -- See if any dock appointments were found. If multiple dock appointments exist,
11003 -- get the one closest to the MAX expected ship date. Since multiple WDD records could be
11004 -- assigned to the delivery, the latest expected ship date from that set is the limiting
11005 -- factor in when the delivery can be shipped out.
11006 IF (l_dock_appt_list.COUNT > 0) THEN
11007 -- Loop through all available dock appointments
11008 -- {{
11009 -- For multiple dock appointments, make sure the 'closest' one is selected. }}
11010 FOR i IN l_dock_appt_list.FIRST .. l_dock_appt_list.LAST LOOP
11011 IF (i = l_dock_appt_list.FIRST) THEN
11012 -- First dock appointment found
11013 l_dock_appointment_id := l_dock_appt_list(i).dock_appointment_id;
11014 l_dock_start_time := l_dock_appt_list(i).start_time;
11015 l_dock_end_time := l_dock_appt_list(i).end_time;
11016
11017 -- Based on the dock schedule method (if present) calculate a single
11018 -- dock appointment time based on the start and end time. If multiple dock
11019 -- appointments exist, this value will be compared with the MAX expected ship
11020 -- date (non-dock appointment) and the closest dock appointment time will be used.
11021 IF (l_dock_schedule_method IS NULL OR l_dock_schedule_method = G_APPT_MEAN_TIME) THEN
11022 l_dock_appt_time := (l_dock_end_time - l_dock_start_time)/2 + l_dock_start_time;
11023 ELSIF (l_dock_schedule_method = G_APPT_START_TIME) THEN
11024 l_dock_appt_time := l_dock_start_time;
11025 ELSIF (l_dock_schedule_method = G_APPT_END_TIME) THEN
11026 l_dock_appt_time := l_dock_end_time;
11027 END IF;
11028 IF (l_debug = 1) THEN
11029 print_debug('Current closest dock appt time: ' ||
11030 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
11031 END IF;
11032 l_progress := '160';
11033 ELSE
11034 -- Calculate the current dock appointment time and compare it to the current
11035 -- best time to see if this one is even closer to the MAX expected ship date.
11036 IF (l_dock_schedule_method IS NULL OR l_dock_schedule_method = G_APPT_MEAN_TIME) THEN
11037 l_current_dock_appt_time := (l_dock_appt_list(i).end_time -
11038 l_dock_appt_list(i).start_time)/2
11039 + l_dock_appt_list(i).start_time;
11040 ELSIF (l_dock_schedule_method = G_APPT_START_TIME) THEN
11041 l_current_dock_appt_time := l_dock_appt_list(i).start_time;
11042 ELSIF (l_dock_schedule_method = G_APPT_END_TIME) THEN
11043 l_current_dock_appt_time := l_dock_appt_list(i).end_time;
11044 END IF;
11045
11046 -- If the dock appointment time is closer to the MAX expected ship date compared
11047 -- to the current best time, update the best dock appointment variables to
11048 -- point to the current dock appointment.
11049 IF (abs(l_current_dock_appt_time - l_max_expected_date) <
11050 abs(l_dock_appt_time - l_max_expected_date)) THEN
11051 l_dock_appointment_id := l_dock_appt_list(i).dock_appointment_id;
11052 l_dock_start_time := l_dock_appt_list(i).start_time;
11053 l_dock_end_time := l_dock_appt_list(i).end_time;
11054 l_dock_appt_time := l_current_dock_appt_time;
11055 END IF;
11056 IF (l_debug = 1) THEN
11057 print_debug('Current closest dock appt time: ' ||
11058 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
11059 END IF;
11060 l_progress := '170';
11061 END IF;
11062 END LOOP;
11063
11064 IF (l_debug = 1) THEN
11065 print_debug('Closest dock appt ID: =========> ' || l_dock_appointment_id);
11066 print_debug('Closest dock appt start time: => ' ||
11067 TO_CHAR(l_dock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
11068 print_debug('Closest dock appt end time: ===> ' ||
11069 TO_CHAR(l_dock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
11070 print_debug('Closest dock appt time: =======> ' ||
11071 TO_CHAR(l_dock_appt_time, 'DD-MON-YYYY HH24:MI:SS'));
11072 END IF;
11073 l_progress := '180';
11074
11075 -- We have now found the closest dock appointment time to the MAX expected ship time
11076 x_dock_appointment_id := l_dock_appointment_id;
11077 x_dock_start_time := l_dock_start_time;
11078 x_dock_end_time := l_dock_end_time;
11079 x_expected_time := l_dock_appt_time;
11080 l_progress := '190';
11081
11082 END IF; -- End of dock appointments found
11083
11084 -- If a dock appointment was not found, just use the MIN and MAX expected ship date
11085 -- retrieved from the cursors as the dock start and end times. The expected time and
11086 -- dock appointment ID output variables will be NULL so the caller knows a dock appointment
11087 -- was not found. If NULL date values were retrieved from the cursor, this means that no
11088 -- WDD records are assigned to the delivery. In that case, return NULL values for the dock
11089 -- start and end time.
11090 -- {{
11091 -- For cases where no dock appointments exist, make sure the min and max expected dates
11092 -- from the WDD records assigned to the delivery are returned. }}
11093 -- {{
11094 -- For deliveries without dock appointments and no WDD records assigned to them, the
11095 -- expected times returned should all be null. }}
11096 IF (l_dock_appt_list.COUNT = 0) THEN
11097 x_dock_appointment_id := NULL;
11098 IF (l_null_dates_retrieved) THEN
11099 x_dock_start_time := NULL;
11100 x_dock_end_time := NULL;
11101 ELSE
11102 x_dock_start_time := l_min_expected_date;
11103 x_dock_end_time := l_max_expected_date;
11104 END IF;
11105 x_expected_time := NULL;
11106 END IF;
11107 l_progress := '200';
11108
11109 IF (l_debug = 1) THEN
11110 print_debug('Dock Appointment ID: => ' || x_dock_appointment_id);
11111 print_debug('Dock start time: =====> ' || TO_CHAR(x_dock_start_time, 'DD-MON-YYYY HH24:MI:SS'));
11112 print_debug('Dock end time: =======> ' || TO_CHAR(x_dock_end_time, 'DD-MON-YYYY HH24:MI:SS'));
11113 print_debug('Expected time: =======> ' || TO_CHAR(x_expected_time, 'DD-MON-YYYY HH24:MI:SS'));
11114 END IF;
11115
11116 <<custom_logic_used>>
11117 IF (l_debug = 1) THEN
11118 print_debug('***End of Get_Expected_Delivery_Time***');
11119 END IF;
11120
11121 EXCEPTION
11122 WHEN FND_API.G_EXC_ERROR THEN
11123 ROLLBACK TO Get_Expected_Delivery_Time_sp;
11124 x_return_status := fnd_api.g_ret_sts_error;
11125 fnd_msg_pub.count_and_get(p_count => x_msg_count,
11126 p_data => x_msg_data);
11127 IF (l_debug = 1) THEN
11128 print_debug('Exiting Get_Expected_Delivery_Time - Execution error: ' ||
11129 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
11130 END IF;
11131
11132 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
11133 ROLLBACK TO Get_Expected_Delivery_Time_sp;
11134 x_return_status := fnd_api.g_ret_sts_unexp_error;
11135 fnd_msg_pub.count_and_get(p_count => x_msg_count,
11136 p_data => x_msg_data);
11137 IF (l_debug = 1) THEN
11138 print_debug('Exiting Get_Expected_Delivery_Time - Unexpected error: ' ||
11139 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
11140 END IF;
11141
11142 WHEN OTHERS THEN
11143 ROLLBACK TO Get_Expected_Delivery_Time_sp;
11144 x_return_status := fnd_api.g_ret_sts_unexp_error;
11145 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11146 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
11147 END IF;
11148 fnd_msg_pub.count_and_get(p_count => x_msg_count,
11149 p_data => x_msg_data);
11150 IF (l_debug = 1) THEN
11151 print_debug('Exiting Get_Expected_Delivery_Time - Others exception: ' ||
11152 l_progress ||' '|| TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS'));
11153 END IF;
11154
11155 END Get_Expected_Delivery_Time;
11156 -- {{ }}
11157 -- {{******************** End Get_Expected_Delivery_Time ********************}}
11158 -- {{ }}
11159
11160
11161 END WMS_XDOCK_PEGGING_PUB;
11162