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