DBA Data[Home] [Help]

PACKAGE BODY: APPS.WMS_XDOCK_PEGGING_PUB

Source


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