DBA Data[Home] [Help]

PACKAGE BODY: APPS.RCV_AVAILABILITY

Source


1 PACKAGE BODY rcv_availability AS
2 /* $Header: RCVAVALB.pls 120.9 2006/10/16 11:47:08 srnatara noship $*/
3    TYPE wms_install_table_type IS TABLE OF BOOLEAN
4       INDEX BY BINARY_INTEGER;
5 
6    g_wms_install_table wms_install_table_type;
7    g_pkg_name CONSTANT VARCHAR2(30)           := 'rcv_availability';
8    g_rti_normalized    VARCHAR2(1);
9 
10    /*
11    normalize_interface_tables is a private helper function for
12    get_available_supply_demand in 12.0, the normalization package was
13    introduced to put all of the information in RTI into a consistent
14    state to allow one-stop shopping for writting SQL queries. This
15    process is normally started by the preprocessor. I want to take
16    advantage of this convience, but since reservations can be run at
17    any time I need to manually execute the package rather than let the
18    preprocessor execute it.
19    The process of normalizing the data can be expensive, so in order
20    to reduce the performance hit I will process the rows in the
21    interface table only once. This is useful considering that this
22    call may be made many times during planned cross docking execution.
23    */
24    PROCEDURE normalize_interface_tables IS
25       PRAGMA AUTONOMOUS_TRANSACTION;
26 
27       CURSOR get_rhi_rows IS
28          SELECT *
29          FROM   rcv_headers_interface
30          WHERE  processing_status_code = 'PENDING';
31 
32       CURSOR get_rti_rows IS
33          SELECT *
34          FROM   rcv_transactions_interface
35          WHERE  processing_status_code = 'PENDING';
36    BEGIN
37       IF (g_rti_normalized IS NOT NULL) THEN --because this is expensive, we only want to run it once per session
38          RETURN;
39       END IF;
40 
41       g_rti_normalized  := 'Y';
42 
43       FOR rhi_row IN get_rhi_rows LOOP
44          BEGIN
45             rcv_default_pkg.default_header(rhi_row);
46             rcv_table_functions.update_rhi_row(rhi_row);
47          EXCEPTION
48             WHEN OTHERS THEN
49                NULL;
50          END;
51       END LOOP;
52 
53       FOR rti_row IN get_rti_rows LOOP
54          IF (rti_row.validation_flag = 'Y') THEN
55             BEGIN
56                rcv_default_pkg.default_transaction(rti_row);
57                rcv_table_functions.update_rti_row(rti_row);
58             EXCEPTION
59                WHEN OTHERS THEN
60                   NULL;
61             END;
62          END IF;
63       END LOOP;
64 
65       COMMIT; --release locks
66    END normalize_interface_tables;
67 
68    /*
69    get_available_supply_demand returns the available quantity in terms
70    of the ***PRIMARY_UNIT_OF_MEASURE*** <-VERY IMPORTANT.  All
71    quantities inside this procedure are kept in terms of
72    primary_unit_of_measure. This is necessary because different
73    transaction rows in rt can be transacted in different units of
74    measure. There are two important quantities being tracked in this
75    procedure: x_rcv_quantity - this is the quantity that has already
76    been received or will be received into receiving, and
77    x_rcv_order_quantity - this is the quantity that was ordered on the
78    backing document. The value returned in x_available_quantity =
79    x_ordered_quantity - x_rcv_quantity
80    */
81    PROCEDURE get_available_supply_demand(
82       x_return_status             OUT NOCOPY    VARCHAR2,
83       x_msg_count                 OUT NOCOPY    NUMBER,
84       x_msg_data                  OUT NOCOPY    VARCHAR2,
85       x_available_quantity        OUT NOCOPY    NUMBER,
86       x_source_uom_code           OUT NOCOPY    VARCHAR2,
87       x_source_primary_uom_code   OUT NOCOPY    VARCHAR2,
88       p_supply_demand_code        IN            NUMBER,
89       p_organization_id           IN            NUMBER,
90       p_item_id                   IN            NUMBER,
91       p_revision                  IN            VARCHAR2,
92       p_lot_number                IN            VARCHAR2,
93       p_subinventory_code         IN            VARCHAR2,
94       p_locator_id                IN            NUMBER,
95       p_supply_demand_type_id     IN            NUMBER,
96       p_supply_demand_header_id   IN            NUMBER,
97       p_supply_demand_line_id     IN            NUMBER,
98       p_supply_demand_line_detail IN            NUMBER,
99       p_lpn_id                    IN            NUMBER,
100       p_project_id                IN            NUMBER,
101       p_task_id                   IN            NUMBER,
102       p_api_version_number        IN            NUMBER,
103       p_init_msg_lst              IN            VARCHAR2
104    ) IS
105       l_api_version_number CONSTANT NUMBER                 := 1.0;
106       l_api_name           CONSTANT VARCHAR2(30)           := 'get_available_supply_demand';
107       l_lpn_id                      NUMBER;--Bug 5329067
108       x_rcv_quantity                NUMBER;
109       x_rcv_order_quantity          NUMBER;
110 
111       CURSOR get_uom_code(
112          p_unit_of_measure mtl_units_of_measure.unit_of_measure%TYPE
113       ) IS
114          SELECT uom_code
115          FROM   mtl_units_of_measure
116          WHERE  unit_of_measure = p_unit_of_measure;
117 
118       /*
119       The following four cursors: get_req_order, get_oe_order,
120       get_ship_order, and get_po_order are responsible for getting the
121       original order quantity from the backing doc regardless of the
122       status of the backing doc
123       */
124       CURSOR get_req_order IS
125          SELECT rl.quantity,
126                 rl.item_id,
127                 rl.unit_meas_lookup_code unit_of_measure,
128                 si.primary_unit_of_measure
129          FROM   po_requisition_lines_all rl,
130                 mtl_system_items si
131          WHERE  rl.requisition_line_id = p_supply_demand_line_id
132          AND    si.inventory_item_id(+) = rl.item_id;
133 
134       CURSOR get_oe_order IS
135          SELECT oel.ordered_quantity quantity,
136                 oel.inventory_item_id item_id,
137                 uom.unit_of_measure,
138                 si.primary_unit_of_measure
139          FROM   oe_order_lines_all oel,
140                 mtl_units_of_measure uom,
141                 mtl_system_items si
142          WHERE  line_id = p_supply_demand_line_id
143          AND    order_quantity_uom = uom_code
144          AND    si.inventory_item_id(+) = oel.inventory_item_id;
145 
146       CURSOR get_ship_order(
147          p_shipment_line_id IN rcv_shipment_lines.shipment_line_id%TYPE
148       ) IS
149          SELECT quantity_shipped quantity,
150                 item_id,
151                 unit_of_measure,
152                 primary_unit_of_measure
153          FROM   rcv_shipment_lines
154          WHERE  shipment_line_id = p_shipment_line_id;
155 
156 	/* Bug. 4693257.
157 	 * We need to get the quantity from po_distributions
158 	 * since we need to match project and task ids.
159 	*/
160       CURSOR get_po_order(
161 	p_project_id IN po_distributions_all.project_id%type,
162 	p_task_id IN po_distributions_all.task_id%type) IS
163          SELECT sum(pod.quantity_ordered) quantity,
164                 pol.item_id,
165                 pol.unit_meas_lookup_code unit_of_measure,
166                 si.primary_unit_of_measure
167          FROM   po_line_locations_all pll,
168                 po_lines_all pol,
169 		po_distributions_all pod,
170                 mtl_system_items si
171          WHERE  pll.line_location_id = p_supply_demand_line_id
172          AND    pll.po_line_id = pol.po_line_id
173 	   AND  si.inventory_item_id(+) = pol.item_id
174 	   AND  nvl(si.organization_id,pll.ship_to_organization_id) =
175 		pll.ship_to_organization_id
176 	 and pod.line_location_id = pll.line_location_id
177 	 and (p_project_id is null or
178 		pod.project_id= p_project_id)
179 	 and(p_task_id is null or
180 	     pod.task_id = p_task_id)
181 	   GROUP BY pol.item_id,
182                 pol.unit_meas_lookup_code,
183                 si.primary_unit_of_measure;
184 
185       /*
186       the following cursors: get_rcv_req_row, get_rcv_oe_row,
187       get_rcv_ship_row, get_rcv_po_row are all the same query, but
188       with different driving where clauses. The cursor used is
189       determined by p_supply_demand_type_id. The cursors return all
190       the rows in RCV_SHIPMENT_LINES and all the receipts/+correction
191       to receipts/shipments in RCV_TRANSACTIONS_INTERFACE that apply
192       to the backing doc
193 
194       The parameters p_organization_id, p_item_id, p_revision,
195       p_lot_number, p_subinventory_code, p_locator_id, p_project_id,
196       and p_task_id are NOT driving parameters. They are coded into
197       the queries in a way that the CBO will not attempt to use them,
198       instead it will always rely on the backing doc as the driving
199       column. These parameters only restrict the scope of a query,
200       they do not enlargen it.
201       */
202       CURSOR get_rcv_req_row IS
203          SELECT DECODE(rti.transaction_type,
204                        'SHIP', rti.quantity,
205                        'RECEIVE', rti.quantity,
206                        'CORRECT', DECODE(rt.transaction_type,
207                                          'SHIP', rti.quantity,
208                                          'RECEIVE', rti.quantity,
209                                          0
210                                         ),
211                        0
212                       ) quantity_shipped,
213                 DECODE(rti.transaction_type,
214                        'DELIVER', rti.quantity,
215                        'CORRECT', DECODE(rt.transaction_type,
216                                          'DELIVER', rti.quantity,
217                                          0
218                                         ),
219                        DECODE(rti.auto_transact_code,
220                               'DELIVER', rti.quantity,
221                               0
222                              )
223                       ) quantity_delivered,
224                 rti.item_id,
225                 rti.unit_of_measure,
226                 rti.primary_unit_of_measure,
227                 rti.to_organization_id
228          FROM   rcv_transactions_interface rti,
229                 rcv_transactions rt
230          WHERE  rti.parent_transaction_id = rt.transaction_id(+)
231          AND    rti.quantity > 0
232          AND    (   rti.transaction_type IN('RECEIVE', 'SHIP', 'DELIVER')
233                  OR (    rti.transaction_type = 'CORRECT'
234                      AND rt.transaction_type IN('RECEIVE', 'DELIVER')))
235          AND    rti.processing_status_code IN('PENDING', 'RUNNING')
236          AND    (   p_organization_id IS NULL
237                  OR p_organization_id = rti.to_organization_id)
238          AND    (   p_item_id IS NULL
239                  OR p_item_id = rti.item_id)
240          AND    (   p_revision IS NULL
241                  OR p_revision = rti.item_revision)
242          AND    (   p_subinventory_code IS NULL
243                  OR p_subinventory_code = rti.subinventory)
244          AND    (   p_locator_id IS NULL
245                  OR p_locator_id = rti.locator_id)
246          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
247                  OR l_lpn_id = rti.lpn_id --Bug 5329067
248                  OR (    l_lpn_id IS NULL--Bug 5329067
249                      AND rti.lpn_id IS NULL))
250          AND    (   p_project_id IS NULL
251                  OR p_project_id = rti.project_id)
252          AND    (   p_task_id IS NULL
253                  OR p_task_id = rti.task_id)
254          AND    rti.requisition_line_id = p_supply_demand_line_id
255          UNION ALL
256          SELECT rsl.quantity_received,
257                  rsl.quantity_received - NVL(rs.quantity, 0) quantity_delivered,
258                 rsl.item_id,
259                 rsl.unit_of_measure,
260                 rsl.primary_unit_of_measure,
261                 rsl.to_organization_id
262          FROM   rcv_shipment_lines rsl,
263                 rcv_supply rs
264          WHERE  rsl.shipment_line_id = rs.shipment_line_id(+)
265          AND    (   p_organization_id IS NULL
266                  OR p_organization_id = rsl.to_organization_id)
267          AND    (   p_item_id IS NULL
268                  OR p_item_id = rsl.item_id)
269          AND    (   p_revision IS NULL
270                  OR p_revision = rsl.item_revision)
271          AND    (   p_subinventory_code IS NULL
272                  OR p_subinventory_code = rsl.to_subinventory)
273          AND    (   p_locator_id IS NULL
274                  OR p_locator_id = rsl.locator_id)
275          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
276                  OR NVL(l_lpn_id, fnd_api.g_miss_num) IN(SELECT NVL(rt.lpn_id, fnd_api.g_miss_num) --Bug 5329067
277                                                          FROM   rcv_transactions rt
278                                                          WHERE  rt.shipment_line_id = rsl.shipment_line_id))
279          AND    (   p_project_id IS NULL
280                  OR p_project_id IN(SELECT rt.project_id
281                                     FROM   rcv_transactions rt
282                                     WHERE  rt.shipment_line_id = rsl.shipment_line_id))
283          AND    (   p_task_id IS NULL
284                  OR p_task_id IN(SELECT rt.task_id
285                                  FROM   rcv_transactions rt
286                                  WHERE  rt.shipment_line_id = rsl.shipment_line_id))
287          AND    rsl.requisition_line_id = p_supply_demand_line_id;
288 
289       CURSOR get_rcv_oe_row IS
290          SELECT DECODE(rti.transaction_type,
291                        --'SHIP', rti.quantity,--dont count
292                        'RECEIVE', rti.quantity,
293                        'CORRECT', DECODE(rt.transaction_type,
294                                          --'SHIP', rti.quantity,--dont count
295                                          'RECEIVE', rti.quantity,
296                                          0
297                                         ),
298                        0
299                       ) quantity_shipped,
300                 DECODE(rti.transaction_type,
301                        'DELIVER', rti.quantity,
302                        'CORRECT', DECODE(rt.transaction_type,
303                                          'DELIVER', rti.quantity,
304                                          0
305                                         ),
306                        DECODE(rti.auto_transact_code,
307                               'DELIVER', rti.quantity,
308                               0
309                              )
310                       ) quantity_delivered,
311                 rti.item_id,
312                 rti.unit_of_measure,
313                 rti.primary_unit_of_measure,
314                 rti.to_organization_id
315          FROM   rcv_transactions_interface rti,
316                 rcv_transactions rt
317          WHERE  rti.parent_transaction_id = rt.transaction_id(+)
318          AND    rti.quantity > 0
319          AND    (   rti.transaction_type IN('RECEIVE', 'SHIP', 'DELIVER')
320                  OR (    rti.transaction_type = 'CORRECT'
321                      AND rt.transaction_type IN('RECEIVE', 'DELIVER')))
322          AND    rti.processing_status_code IN('PENDING', 'RUNNING')
323          AND    (   p_organization_id IS NULL
324                  OR p_organization_id = rti.to_organization_id)
325          AND    (   p_item_id IS NULL
326                  OR p_item_id = rti.item_id)
327          AND    (   p_revision IS NULL
328                  OR p_revision = rti.item_revision)
329          AND    (   p_subinventory_code IS NULL
330                  OR p_subinventory_code = rti.subinventory)
331          AND    (   p_locator_id IS NULL
332                  OR p_locator_id = rti.locator_id)
333          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
334                  OR l_lpn_id = rti.lpn_id --Bug 5329067
335                  OR (    l_lpn_id IS NULL --Bug 5329067
336                      AND rti.lpn_id IS NULL))
337          AND    (   p_project_id IS NULL
338                  OR p_project_id = rti.project_id)
339          AND    (   p_task_id IS NULL
340                  OR p_task_id = rti.task_id)
341          AND    rti.oe_order_line_id = p_supply_demand_line_id
342          UNION ALL
343          SELECT rsl.quantity_received,
344                  rsl.quantity_received - NVL(rs.quantity, 0) quantity_delivered,
345                 rsl.item_id,
346                 rsl.unit_of_measure,
347                 rsl.primary_unit_of_measure,
348                 rsl.to_organization_id
349          FROM   rcv_shipment_lines rsl,
350                 rcv_supply rs
351          WHERE  rsl.shipment_line_id = rs.shipment_line_id(+)
352          AND    (   p_organization_id IS NULL
353                  OR p_organization_id = rsl.to_organization_id)
354          AND    (   p_item_id IS NULL
355                  OR p_item_id = rsl.item_id)
356          AND    (   p_revision IS NULL
357                  OR p_revision = rsl.item_revision)
358          AND    (   p_subinventory_code IS NULL
359                  OR p_subinventory_code = rsl.to_subinventory)
360          AND    (   p_locator_id IS NULL
361                  OR p_locator_id = rsl.locator_id)
362          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
363                  OR NVL(l_lpn_id, fnd_api.g_miss_num) IN(SELECT NVL(rt.lpn_id, fnd_api.g_miss_num)--Bug 5329067
364                                                          FROM   rcv_transactions rt
365                                                          WHERE  rt.shipment_line_id = rsl.shipment_line_id))
366          AND    (   p_project_id IS NULL
367                  OR p_project_id IN(SELECT rt.project_id
368                                     FROM   rcv_transactions rt
369                                     WHERE  rt.shipment_line_id = rsl.shipment_line_id))
370          AND    (   p_task_id IS NULL
371                  OR p_task_id IN(SELECT rt.task_id
372                                  FROM   rcv_transactions rt
373                                  WHERE  rt.shipment_line_id = rsl.shipment_line_id))
374          AND    rsl.oe_order_line_id = p_supply_demand_line_id;
375 
376       /*
377       get_rcv_ship_row is unique because I want to use it for both
378       asn's and intransit so I have made the line_id a parameter
379       */
380       /* Bug 4642399.
381        * We do not need the rti.quantity when transaction_type
382        * is SHIP since it actually gets the current shipped_qty
383        * for both ASN and Intrasit transactions.
384       */
385       CURSOR get_rcv_ship_row(
386          p_shipment_line_id IN rcv_shipment_lines.shipment_line_id%TYPE
387       ) IS
388          SELECT DECODE(rti.transaction_type,
389                        --'SHIP', rti.quantity,
390                        'RECEIVE', rti.quantity,
391                        'CORRECT', DECODE(rt.transaction_type,
392                                          'SHIP', rti.quantity,
393                                          'RECEIVE', rti.quantity,
394                                          0
395                                         ),
396                        0
397                       ) quantity_shipped,
398                 DECODE(rti.transaction_type,
399                        'DELIVER', rti.quantity,
400                        'CORRECT', DECODE(rt.transaction_type,
401                                          'DELIVER', rti.quantity,
402                                          0
403                                         ),
404                        DECODE(rti.auto_transact_code,
405                               'DELIVER', rti.quantity,
406                               0
407                              )
408                       ) quantity_delivered,
409                 rti.item_id,
410                 rti.unit_of_measure,
411                 rti.primary_unit_of_measure,
412                 rti.to_organization_id
413          FROM   rcv_transactions_interface rti,
414                 rcv_transactions rt
415          WHERE  rti.parent_transaction_id = rt.transaction_id(+)
416          AND    rti.quantity > 0
417          AND    (   rti.transaction_type IN('RECEIVE', 'SHIP', 'DELIVER')
418                  OR (    rti.transaction_type = 'CORRECT'
419                      AND rt.transaction_type IN('RECEIVE', 'DELIVER')))
420          AND    rti.processing_status_code IN('PENDING', 'RUNNING')
421          AND    (   p_organization_id IS NULL
422                  OR p_organization_id = rti.to_organization_id)
423          AND    (   p_item_id IS NULL
424                  OR p_item_id = rti.item_id)
425          AND    (   p_revision IS NULL
426                  OR p_revision = rti.item_revision)
427          AND    (   p_subinventory_code IS NULL
428                  OR p_subinventory_code = rti.subinventory)
429          AND    (   p_locator_id IS NULL
430                  OR p_locator_id = rti.locator_id)
431          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
432                  OR l_lpn_id = rti.lpn_id--Bug 5329067
433                  OR (    l_lpn_id IS NULL --Bug 5329067
434                      AND rti.lpn_id IS NULL))
435          AND    (   p_project_id IS NULL
436                  OR p_project_id = rti.project_id)
437          AND    (   p_task_id IS NULL
438                  OR p_task_id = rti.task_id)
439          AND    rti.shipment_line_id = p_shipment_line_id
440          UNION ALL
441          SELECT rsl.quantity_received,
442                  rsl.quantity_received - NVL(rs.quantity, 0) quantity_delivered,
443                 rsl.item_id,
444                 rsl.unit_of_measure,
445                 rsl.primary_unit_of_measure,
446                 rsl.to_organization_id
447          FROM   rcv_shipment_lines rsl,
448                 rcv_supply rs
449          WHERE  rsl.shipment_line_id = rs.shipment_line_id(+)
450          AND    (   p_organization_id IS NULL
451                  OR p_organization_id = rsl.to_organization_id)
452          AND    (   p_item_id IS NULL
453                  OR p_item_id = rsl.item_id)
454          AND    (   p_revision IS NULL
455                  OR p_revision = rsl.item_revision)
456          AND    (   p_subinventory_code IS NULL
457                  OR p_subinventory_code = rsl.to_subinventory)
458          AND    (   p_locator_id IS NULL
459                  OR p_locator_id = rsl.locator_id)
460          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
461                  OR NVL(l_lpn_id, fnd_api.g_miss_num) IN(SELECT NVL(rt.lpn_id, fnd_api.g_miss_num) --Bug 5329067
462                                                          FROM   rcv_transactions rt
463                                                          WHERE  rt.shipment_line_id = rsl.shipment_line_id))
464          AND    (   p_project_id IS NULL
465                  OR p_project_id IN(SELECT rt.project_id
466                                     FROM   rcv_transactions rt
467                                     WHERE  rt.shipment_line_id = rsl.shipment_line_id))
468          AND    (   p_task_id IS NULL
469                  OR p_task_id IN(SELECT rt.task_id
470                                  FROM   rcv_transactions rt
471                                  WHERE  rt.shipment_line_id = rsl.shipment_line_id))
472          AND    rsl.shipment_line_id = p_shipment_line_id;
473 
474       CURSOR get_rcv_po_row IS
475          SELECT DECODE(rti.transaction_type,
476                        'SHIP', rti.quantity,
477                        'RECEIVE', rti.quantity,
478                        'CORRECT', DECODE(rt.transaction_type,
479                                          'SHIP', rti.quantity,
480                                          'RECEIVE', rti.quantity,
481                                          0
482                                         ),
483                         'RETURN TO CUSTOMER', DECODE(rt.transaction_type,
484                                                    'RECEIVE', -1 * rti.quantity,
485                                                                0
486                                                      ), --Return txn is similar as -ve Correction. So make the qty
487                                                         --as -ve in order to calculate the available qty correctly
488                         'RETURN TO VENDOR', DECODE(rt.transaction_type,
489                                                    'RECEIVE', -1 * rti.quantity,
490                                                                0
491                                                      ),
492 
493                         0
494                        )quantity_received, --Bug 5329067
495                 DECODE(rti.transaction_type,
496                        'DELIVER', rti.quantity,
497                        'CORRECT', DECODE(rt.transaction_type,
498                                          'DELIVER', rti.quantity,
499                                          0
500                                         ),
501                         'RETURN TO CUSTOMER', DECODE(rt.transaction_type,
502                                                      'DELIVER', -1 * rti.quantity,
503                                                       0
504                                                      ), --Returns txn is similar as -ve Correction. So make the qty
505                                                          --as -ve in order to calculate the available qty correctly
506                         'RETURN TO VENDOR', DECODE(rt.transaction_type,
507                                                     'DELIVER', -1 * rti.quantity,
508                                                      0
509                                                      ),
510                         'RETURN TO RECEIVING', DECODE(rt.transaction_type,
511                                                       'DELIVER', -1 * rti.quantity,
512                                                        0
513                                                      ),
514                         DECODE(rti.auto_transact_code,
515                               'DELIVER', rti.quantity,
516                               0
517                              )
518                       ) quantity_delivered, --Bug 5329067
519                 rti.item_id,
520                 rti.unit_of_measure,
521                 rti.primary_unit_of_measure,
522                 rti.to_organization_id
523          FROM   rcv_transactions_interface rti,
524                 rcv_transactions rt
525          WHERE  rti.parent_transaction_id = rt.transaction_id(+)
526          AND    (    rti.quantity > 0
527                   OR (rti.quantity < 0 AND rti.transaction_type = 'CORRECT')
528                 )--Bug 5329067
529          AND    (    rti.transaction_type IN('RECEIVE', 'SHIP', 'DELIVER')
530                   OR (    rti.transaction_type = 'CORRECT'
531                       AND rt.transaction_type IN('RECEIVE', 'DELIVER')
532                      )
533                   OR (    rti.transaction_type IN ('RETURN TO CUSTOMER','RETURN TO VENDOR', 'RETURN TO RECEIVING')
534                       AND rt.transaction_type IN('RECEIVE', 'DELIVER')
535                      )
536                 )--Bug 5329067
537          AND    rti.processing_status_code IN('PENDING', 'RUNNING')
538          AND    (   p_organization_id IS NULL
539                  OR p_organization_id = rti.to_organization_id)
540          AND    (   p_item_id IS NULL
541                  OR p_item_id = rti.item_id)
542          AND    (   p_revision IS NULL
543                  OR p_revision = rti.item_revision)
544          AND    (   p_subinventory_code IS NULL
545                  OR p_subinventory_code = rti.subinventory)
546          AND    (   p_locator_id IS NULL
547                  OR p_locator_id = rti.locator_id)
548          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
549                  OR l_lpn_id = rti.lpn_id --Bug 5329067
550                  OR (    l_lpn_id IS NULL--Bug 5329067
551                      AND rti.lpn_id IS NULL))
552          AND    (   p_project_id IS NULL
553                  OR p_project_id = rti.project_id)
554          AND    (   p_task_id IS NULL
555                  OR p_task_id = rti.task_id)
556          AND    rti.po_line_location_id = p_supply_demand_line_id
557          UNION ALL
558          SELECT rsl.quantity_received quantity_received, --Bug 5329067
559                  rsl.quantity_received - NVL(rs.quantity, 0) quantity_delivered,
560                 rsl.item_id,
561                 rsl.unit_of_measure,
562                 rsl.primary_unit_of_measure,
563                 rsl.to_organization_id
564          FROM   rcv_shipment_lines rsl,
565                 rcv_supply rs
566          WHERE  rsl.shipment_line_id = rs.shipment_line_id(+)
567          AND    (   p_organization_id IS NULL
568                  OR p_organization_id = rsl.to_organization_id)
569          AND    (   p_item_id IS NULL
570                  OR p_item_id = rsl.item_id)
571          AND    (   p_revision IS NULL
572                  OR p_revision = rsl.item_revision)
573          AND    (   p_subinventory_code IS NULL
574                  OR p_subinventory_code = rsl.to_subinventory)
575          AND    (   p_locator_id IS NULL
576                  OR p_locator_id = rsl.locator_id)
577          AND    (   l_lpn_id = fnd_api.g_miss_num --Bug 5329067
578                  OR NVL(l_lpn_id, fnd_api.g_miss_num) IN(SELECT NVL(rt.lpn_id, fnd_api.g_miss_num) --Bug 5329067
579                                                          FROM   rcv_transactions rt
580                                                          WHERE  rt.shipment_line_id = rsl.shipment_line_id))
581          AND    (   p_project_id IS NULL
582                  OR p_project_id IN(SELECT rt.project_id
583                                     FROM   rcv_transactions rt
584                                     WHERE  rt.shipment_line_id = rsl.shipment_line_id))
585          AND    (   p_task_id IS NULL
586                  OR p_task_id IN(SELECT rt.task_id
587                                  FROM   rcv_transactions rt
588                                  WHERE  rt.shipment_line_id = rsl.shipment_line_id))
589          AND    rsl.po_line_location_id = p_supply_demand_line_id;
590 
591       x_order_row                   get_po_order%ROWTYPE;
592 
593       /*
594       get_wms_install is a local helper function that takes an org_id
595       and memoizes it in order to increase performance because we are
596       likely to perform the same check against wms many times.
597       */
598       FUNCTION get_wms_install(
599          p_organization_id NUMBER
600       )
601          RETURN BOOLEAN IS
602       BEGIN
603          IF g_wms_install_table.EXISTS(p_organization_id) THEN
604             RETURN g_wms_install_table(p_organization_id);
605          END IF;
606 
607          g_wms_install_table(p_organization_id)  := wms_install.check_install(x_return_status,
608                                                                               x_msg_count,
609                                                                               x_msg_data,
610                                                                               p_organization_id
611                                                                              );
612          RETURN g_wms_install_table(p_organization_id);
613       END get_wms_install;
614 
615       /*
616       update_rcv_quantity is a local helper function that takes care
617       of the house keeping to keep the code easy to read. This
618       procedure increments x_local_quantity and
619       x_local_quantity appropriately - ensuring to keep
620       everything in the primary_unit_of_measure.
621       */
622       PROCEDURE update_rcv_quantity(
623          p_row get_rcv_po_row%ROWTYPE
624       ) IS
625          x_local_quantity NUMBER;
626       BEGIN
627          x_local_quantity  := 0;
628 
629          IF (get_wms_install(p_row.to_organization_id)) THEN
630             po_uom_s.uom_convert(NVL(p_row.quantity_received, 0),
631                                  p_row.unit_of_measure,
632                                  p_row.item_id,
633                                  NVL(p_row.primary_unit_of_measure, p_row.unit_of_measure),
634                                  x_local_quantity
635                                 );
636          ELSE --non wms org: count the quantity delivered
637             po_uom_s.uom_convert(NVL(p_row.quantity_delivered, 0),
638                                  p_row.unit_of_measure,
639                                  p_row.item_id,
640                                  NVL(p_row.primary_unit_of_measure, p_row.unit_of_measure),
641                                  x_local_quantity
642                                 );
643          END IF;
644 
645          /*
646          pessimistic logging - assume all beneficial transactions fail
647          */
648          /** Bug 5329067:
649           *  x_local_quantity can hold -ve values in case of 'RETURN' txn and
650           *  -ve CORRECTION txn. So commented the check for the value > 0 for
651           *  the variable x_local_quantity.
652           */
653 --         IF (x_local_quantity > 0) THEN
654             x_rcv_quantity  := x_rcv_quantity + x_local_quantity;
655 --         END IF;
656       EXCEPTION
657          WHEN OTHERS THEN
658             NULL;
659       END update_rcv_quantity;
660    BEGIN
661       x_return_status       := fnd_api.g_ret_sts_error;
662 
663       --  Standard call to check for call compatibility
664       IF NOT fnd_api.compatible_api_call(l_api_version_number,
665                                          p_api_version_number,
666                                          l_api_name,
667                                          g_pkg_name
668                                         ) THEN
669          RAISE fnd_api.g_exc_unexpected_error;
670       END IF;
671 
672       --  Initialize message list.
673       IF fnd_api.to_boolean(p_init_msg_lst) THEN
674          fnd_msg_pub.initialize;
675       END IF;
676 
677       IF (   p_supply_demand_code IS NULL
678           OR p_supply_demand_type_id IS NULL
679           OR p_supply_demand_header_id IS NULL
680           OR p_supply_demand_line_id IS NULL) THEN
681          fnd_message.set_name('RCV', 'RCV_INVALID_NULL');
682          fnd_msg_pub.ADD;
683          RAISE fnd_api.g_exc_error;
684       END IF;
685 
686      /** Bug 5329067:
687       *  If the p_lpn_id is passed as 'null' to the procedure get_available_supply_demand(), then
688       *  we have to treat it same as the fnd_api.g_miss_num. As of now reservation in receiving is not
689       *  maintained at the LPN level, so we can treat the 'null' value as fnd_api.g_miss_num.
690       */
691      IF p_lpn_id is null then --Bug 5329067
692          l_lpn_id := fnd_api.g_miss_num;
693      ELSE
694          l_lpn_id := p_lpn_id;
695      END IF;
696 
697       normalize_interface_tables; --this makes sure we can query rti via the header and line id's
698       x_rcv_quantity        := 0;
699       x_rcv_order_quantity  := 0;
700 
701       /*
702       The logic below first defaults x_rcv_order_quantity from the
703       backing docs. It then loops through all the rows in
704       rcv_transactions_interface (RTI) and rcv_shipment_lines (RSL).
705       If the row is in RSL then it increases the running value of
706       x_rcv_quantity by shipped_quantity for non-wms orgs and increases the value
707       of x_rcv_quantity by received_quantity for wms orgs. We know that RSL's
708       shipped_quantity and receipt_quantity are an accurate summation of all rcv_transaction
709       records for that backing doc. If the row is in RTI and the RTI
710       row is a 'RECEIVE' or a positive correction to a 'RECEIVE' then
711       it increases the running value of x_rcv_quantity for wms orgs, else if
712       the RTI row is a 'SHIP' then it increases the running value of
713       x_rcv_quantity.
714 
715       This is to avoid double counting. If I have a PO for quantity
716       100, and I have already processed an ASN for quantity 50, a
717       processed receipt for quantity 10, a pending delivery for
718       quantity 5 for that receipt, and a new pending receipt for
719       quantity 3 then in a WMS installation I want to return an
720       available quantity of 87 = (100 - 10 - 3) or 50 = (100 - 50) in
721       a non-WMS installation. The deliver has already been accounted
722       for in the 'RECEIVE' so the reason for only looking at these RTI
723       types is to avoid double counting.
724       */
725       IF (p_supply_demand_type_id IN(7, 17)) THEN --internal and external req
726          OPEN get_req_order;
727          FETCH get_req_order INTO x_order_row;
728          CLOSE get_req_order;
729 
730          FOR c_rcv_row IN get_rcv_req_row LOOP
731             update_rcv_quantity(c_rcv_row);
732          END LOOP;
733       ELSIF(p_supply_demand_type_id IN(2, 8, 12)) THEN --sales order, rma, and intenal order
734          OPEN get_oe_order;
735          FETCH get_oe_order INTO x_order_row;
736          CLOSE get_oe_order;
737 
738          FOR c_rcv_row IN get_rcv_oe_row LOOP
739             update_rcv_quantity(c_rcv_row);
740          END LOOP;
741       ELSIF(p_supply_demand_type_id IN(26)) THEN --intransit
742          OPEN get_ship_order(p_supply_demand_line_id);
743          FETCH get_ship_order INTO x_order_row;
744          CLOSE get_ship_order;
745 
746          FOR c_rcv_row IN get_rcv_ship_row(p_supply_demand_line_id) LOOP
747             update_rcv_quantity(c_rcv_row);
748          END LOOP;
749       ELSIF(p_supply_demand_type_id IN(25)) THEN --asn
750          OPEN get_ship_order(p_supply_demand_line_detail);
751          FETCH get_ship_order INTO x_order_row;
752          CLOSE get_ship_order;
753 
754          FOR c_rcv_row IN get_rcv_ship_row(p_supply_demand_line_detail) LOOP
755             update_rcv_quantity(c_rcv_row);
756          END LOOP;
757       ELSE --po
758          OPEN get_po_order(p_project_id,p_task_id);
759          FETCH get_po_order INTO x_order_row;
760          CLOSE get_po_order;
761 
762          FOR c_rcv_row IN get_rcv_po_row LOOP
763             update_rcv_quantity(c_rcv_row);
764          END LOOP;
765       END IF;
766 
767 /* Bug 4901404: When the unit_of_measure and primary_unit_of_measure
768                 are null, no need to call the uom_convert procedure and
769 		we can default the value of x_available_quantity to Zero */
770 
771       IF x_order_row.unit_of_measure IS NOT NULL THEN --Bug: 4901404
772          po_uom_s.uom_convert(NVL(x_order_row.quantity, 0),
773                            x_order_row.unit_of_measure,
774                            x_order_row.item_id,
775                            NVL(x_order_row.primary_unit_of_measure, x_order_row.unit_of_measure),
776                            x_rcv_order_quantity
777                           );
778          x_rcv_order_quantity  := NVL(x_rcv_order_quantity, 0);
779          x_available_quantity  := x_rcv_order_quantity - x_rcv_quantity;
780 
781         --Bug 5313645
782         --Since we are converting the available quantity to primary uom
783         --always. We should be passing the primary uom code in x_source_uom_code        --Commenting out the following code.
784 
785        /*OPEN get_uom_code(x_order_row.unit_of_measure);
786          FETCH get_uom_code INTO x_source_uom_code;
787          CLOSE get_uom_code;
788        */
789          OPEN get_uom_code(x_order_row.primary_unit_of_measure);
790          FETCH get_uom_code INTO x_source_primary_uom_code;
791          CLOSE get_uom_code;
792 
793          x_source_uom_code := x_source_primary_uom_code;
794 
795          IF (x_available_quantity IS NULL) THEN
796             fnd_message.set_name('RCV', 'RCV_UNEXPECTED_NULL');
797             fnd_msg_pub.ADD;
798             RAISE fnd_api.g_exc_error;
799          END IF;
800 
801          IF (x_available_quantity < 0) THEN
802             x_available_quantity  := 0;
803          END IF;
804       ELSE -- x_order_row.unit_of_measure is NULL
805          x_available_quantity := 0;
806       END IF; /* Bug:4901404 fix ends*/
807 
808       x_return_status       := fnd_api.g_ret_sts_success;
809    EXCEPTION
810       WHEN fnd_api.g_exc_error THEN
811          x_return_status  := fnd_api.g_ret_sts_error;
812          --  Get message count and data
813          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
814       WHEN fnd_api.g_exc_unexpected_error THEN
815          x_return_status  := fnd_api.g_ret_sts_unexp_error;
816          --  Get message count and data
817          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
818       WHEN OTHERS THEN
819          x_return_status  := fnd_api.g_ret_sts_unexp_error;
820 
821          IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
822             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
823          END IF;
824 
825          --  Get message count and data
826          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
827    END get_available_supply_demand;
828 
829    /*
830    validate_supply_demand does a lookup against the given backing docs
831    and returns a valid flag if the document is open, approved, and
832    waiting for receipts
833    */
834    PROCEDURE validate_supply_demand(
835       x_return_status             OUT NOCOPY    VARCHAR2,
836       x_msg_count                 OUT NOCOPY    NUMBER,
837       x_msg_data                  OUT NOCOPY    VARCHAR2,
838       x_valid_status              OUT NOCOPY    VARCHAR2,
839       p_organization_id           IN            NUMBER,
840       p_item_id                   IN            NUMBER,
841       p_supply_demand_code        IN            NUMBER,
842       p_supply_demand_type_id     IN            NUMBER,
843       p_supply_demand_header_id   IN            NUMBER,
844       p_supply_demand_line_id     IN            NUMBER,
845       p_supply_demand_line_detail IN            NUMBER,
846       p_demand_ship_date          IN            DATE,
847       p_expected_receipt_date     IN            DATE,
848       p_api_version_number        IN            NUMBER,
849       p_init_msg_lst              IN            VARCHAR2
850    ) IS
851       l_api_version_number CONSTANT NUMBER       := 1.0;
852       l_api_name           CONSTANT VARCHAR2(30) := 'get_available_supply_demand';
853       l_lookup_code                 VARCHAR2(20);
854    BEGIN
855       x_return_status  := fnd_api.g_ret_sts_error;
856       x_valid_status   := 'N';
857 
858       --  Standard call to check for call compatibility
859       IF NOT fnd_api.compatible_api_call(l_api_version_number,
860                                          p_api_version_number,
861                                          l_api_name,
862                                          g_pkg_name
863                                         ) THEN
864          RAISE fnd_api.g_exc_unexpected_error;
865       END IF;
866 
867       --  Initialize message list.
868       IF fnd_api.to_boolean(p_init_msg_lst) THEN
869          fnd_msg_pub.initialize;
870       END IF;
871 
872       IF (   p_supply_demand_code IS NULL
873           OR p_supply_demand_type_id IS NULL
874           OR p_supply_demand_header_id IS NULL
875           OR p_supply_demand_line_id IS NULL) THEN
876          fnd_message.set_name('RCV', 'RCV_INVALID_NULL');
877          fnd_msg_pub.ADD;
878          RAISE fnd_api.g_exc_error;
879       END IF;
880 
881       /*
882       The following section will attempt to use the backing docs to
883       query if a valid open doc exists for the various source types.
884       If the query fails then the exception handler will set the valid
885       flag to N
886       */
887       BEGIN
888          IF (p_supply_demand_type_id IN(7, 17)) THEN --interanl and external req
889             IF (p_supply_demand_type_id = 17) THEN --external req
890                l_lookup_code  := 'PURCHASE';
891             ELSE --internal req
892                l_lookup_code  := 'INTERNAL';
893             END IF;
894 
895 	    /* Bug 4619856.
896 	     * Change all the table to base tables.
897 	    */
898             SELECT 'Y'
899             INTO   x_valid_status
900             FROM   po_requisition_lines_all rl,
901                    po_requisition_headers_all rh
902             WHERE  rh.requisition_header_id = rl.requisition_header_id
903             AND    type_lookup_code = l_lookup_code
904             AND    authorization_status = 'APPROVED'
905             AND    NVL(rl.cancel_flag, 'N') = 'N'
906             AND    NVL(rl.closed_code, 'OPEN') = 'OPEN'
907             AND    NVL(rh.closed_code, 'OPEN') = 'OPEN'
908             AND    document_type_code IS NULL
909             AND    destination_type_code <> 'EXPENSE'
910             AND    (   p_organization_id IS NULL
911                     OR p_organization_id = rl.destination_organization_id)
912             AND    (   p_item_id IS NULL
913                     OR p_item_id = rl.item_id)
914             AND    rl.requisition_line_id = p_supply_demand_line_id
915             AND    rh.requisition_header_id = p_supply_demand_header_id;
916          ELSIF(p_supply_demand_type_id IN(2, 8, 12)) THEN --sales order, rma, and internal order
917             IF (p_supply_demand_type_id = 12) THEN --rma
918                l_lookup_code  := 'RETURN';
919             ELSE --sales order and internal order
920                l_lookup_code  := 'ORDER';
921             END IF;
922 
923 	    /* Bug 4619856.
924 	     * Change all the table to base tables.
925 	    */
926             SELECT 'Y'
927             INTO   x_valid_status
928             FROM   oe_order_lines_all
929             WHERE  open_flag = 'Y'
930             AND    line_category_code = l_lookup_code
931             AND    (   p_organization_id IS NULL
932                     OR p_organization_id = deliver_to_org_id)
933             AND    (   p_item_id IS NULL
934                     OR p_item_id = inventory_item_id)
935             AND    line_id = p_supply_demand_line_id
936             AND    header_id = p_supply_demand_header_id;
937          ELSIF(p_supply_demand_type_id IN(26)) THEN --intransit
938             SELECT 'Y'
939             INTO   x_valid_status
940             FROM   rcv_shipment_lines rsl,
941                    rcv_shipment_headers rsh
942             WHERE  shipment_line_status_code IN('EXPECTED', 'PARTIALLY RECEIVED')
943             AND    rsl.shipment_header_id = rsh.shipment_header_id
944             AND    (   p_organization_id IS NULL
945                     OR p_organization_id = rsl.to_organization_id)
946             AND    (   p_item_id IS NULL
947                     OR p_item_id = rsl.item_id)
948             AND    rsl.shipment_line_id = p_supply_demand_line_id
949             AND    rsl.shipment_header_id = p_supply_demand_header_id;
950          ELSE --po's and asn's
951 	    /* Bug 4619856.
952 	     * Change all the table to base tables.
953 	    */
954             SELECT 'Y'
955             INTO   x_valid_status
956             FROM   po_line_locations_all pll,
957                    po_lines_all pol,
958                    po_headers_all poh
959             WHERE  pol.po_header_id = poh.po_header_id
960             AND    pll.po_line_id = pol.po_line_id
961             AND    NVL(pll.approved_flag, 'N') = 'Y'
962             AND    NVL(pol.closed_code, 'OPEN') <> 'FINALLY CLOSED'
963             AND    NVL(pll.cancel_flag, 'N') = 'N'
964             AND    pll.shipment_type IN('STANDARD', 'BLANKET', 'SCHEDULED')
965             AND    (   p_organization_id IS NULL
966                     OR p_organization_id = pll.ship_to_organization_id)
967             AND    (   p_item_id IS NULL
968                     OR p_item_id = pol.item_id)
969             AND    pll.line_location_id = p_supply_demand_line_id
970             AND    pol.po_header_id = p_supply_demand_header_id;
971 
972             --already passed the first check for asn's, now perform the second
973             IF (p_supply_demand_type_id IN(25)) THEN --asn
974                SELECT 'Y'
975                INTO   x_valid_status
976                FROM   rcv_shipment_lines rsl,
977                       rcv_shipment_headers rsh
978                WHERE  shipment_line_status_code IN('EXPECTED', 'PARTIALLY RECEIVED')
979                AND    rsl.shipment_header_id = rsh.shipment_header_id
980                AND    rsl.shipment_line_id = p_supply_demand_line_detail
981                AND    rsl.po_line_location_id = p_supply_demand_line_id
982                AND    rsl.po_header_id = p_supply_demand_header_id;
983             END IF;
984          END IF;
985       EXCEPTION
986          WHEN OTHERS THEN
987             x_valid_status  := 'N';
988       END;
989 
990       x_return_status  := fnd_api.g_ret_sts_success;
991    EXCEPTION
992       WHEN fnd_api.g_exc_error THEN
993          x_return_status  := fnd_api.g_ret_sts_error;
994          --  Get message count and data
995          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
996       WHEN fnd_api.g_exc_unexpected_error THEN
997          x_return_status  := fnd_api.g_ret_sts_unexp_error;
998          --  Get message count and data
999          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
1000       WHEN OTHERS THEN
1001          x_return_status  := fnd_api.g_ret_sts_unexp_error;
1002 
1003          IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1004             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1005          END IF;
1006 
1007          --  Get message count and data
1008          fnd_msg_pub.count_and_get(p_count    => x_msg_count, p_data => x_msg_data);
1009    END validate_supply_demand;
1010 END rcv_availability;