DBA Data[Home] [Help]

PACKAGE BODY: APPS.OPI_DBI_WMS_CAPACITY_UTZ_PKG

Source


1 PACKAGE BODY opi_dbi_wms_capacity_utz_pkg AS
2 /*$Header: OPIDEWCUTZB.pls 120.0 2005/05/24 18:25:37 appldev noship $ */
3 
4 
5 /**************************************************
6 * File scope variables
7 **************************************************/
8 
9 -- Package level variables for session info-
10 -- including schema name for truncating and
11 -- collecting stats. Initialized in check_global_setup.
12 s_opi_schema      VARCHAR2(30);
13 s_status          VARCHAR2(30);
14 s_industry        VARCHAR2(30);
15 
16 -- Package level variables for the standard who columns
17 s_user_id                   NUMBER;
18 s_login_id                  NUMBER;
19 s_program_id                NUMBER;
20 s_program_login_id          NUMBER;
21 s_program_application_id    NUMBER;
22 s_request_id                NUMBER;
23 
24 -- Weight and Volume reporting UOMs
25 s_wt_rep_uom_code VARCHAR2 (3);
26 s_vol_rep_uom_code VARCHAR2 (3);
27 
28 /**************************************************
29 * Common Procedures (to locator capacity and item storage computations)
30 *
31 * File scope functions (not in spec)
32 **************************************************/
33 
34 -- Global variable setup and verification
35 PROCEDURE global_setup;
36 
37 -- Print out error message in a consistent manner
38 FUNCTION err_mesg (p_mesg IN VARCHAR2,
39                    p_proc_name IN VARCHAR2,
40                    p_stmt_id IN NUMBER)
41     RETURN VARCHAR2;
42 
43 -- Print stage done message
44 PROCEDURE print_stage_done_mesg (p_proc_name IN VARCHAR2,
45                                  p_stmt_id IN NUMBER);
46 
47 -- Truncate/sets up relevant tables
48 PROCEDURE setup_tables;
49 
50 
51 /**************************************************
52  * Warehouse Capacity Related procedures
53  **************************************************/
54 
55 -- Extract locator capacities into the subinventory staging table
56 PROCEDURE extract_locator_capacities (p_wt_rep_uom_code IN VARCHAR2,
57                                       p_vol_rep_uom_code IN VARCHAR2);
58 
59 -- Summarize the locator capacities to the subinventory and
60 -- organization levels.
61 PROCEDURE summarize_capacities;
62 
63 -- Report missing rates/errors
64 FUNCTION check_locator_setup_errors
65     RETURN BOOLEAN;
66 
67 /**************************************************
68  * Item Storage Related procedures
69  **************************************************/
70 -- Extract item storage details into the item fact table
71 PROCEDURE extract_item_storage (p_wt_rep_uom_code IN VARCHAR2,
72                                 p_vol_rep_uom_code IN VARCHAR2);
73 
74 
75 -- Report missing rates/errors
76 FUNCTION check_item_setup_errors
77     RETURN BOOLEAN;
78 
79 /**************************************************
80  * Common Procedures Definitions
81  **************************************************/
82 
83 /*  global_setup
84 
85     Performs global setup of file scope variables and does any checking
86     needed for global DBI setups.
87 
88     Parameters: None
89 
90     History:
91     Date        Author              Action
92     12/01/04    Dinkar Gupta        Defined function.
93 
94 */
95 PROCEDURE global_setup
96 IS
97     l_proc_name CONSTANT VARCHAR2 (40) := 'global_setup';
98     l_stmt_id NUMBER;
99 
100 
101     -- Cursor to get the reporting UOM for a certain measure code.
102     -- Can be null if not set up.
103     CURSOR get_rep_uom_csr (p_measure_code VARCHAR2)
104     IS
105     SELECT rep_uom_code
106       FROM opi_dbi_rep_uoms
107       WHERE measure_code = p_measure_code;
108 
109 BEGIN
110 
111     -- Initialization block
112     l_stmt_id := 0;
113 
114     l_stmt_id := 10;
115     -- Obtain the OPI schema name to allow truncation of various tables
116     -- get session parameters
117     IF (NOT (fnd_installation.get_app_info('OPI', s_status, s_industry,
118                                            s_opi_schema))) THEN
119         RAISE SCHEMA_INFO_NOT_FOUND;
120     END IF;
121 
122     l_stmt_id := 20;
123     -- Package level variables for the user logged in
124     s_user_id := nvl(fnd_global.user_id, -1);
125     s_login_id := nvl(fnd_global.login_id, -1);
126     s_program_id := nvl (fnd_global.conc_program_id, -1);
127     s_program_login_id := nvl (fnd_global.conc_login_id, -1);
128     s_program_application_id := nvl (fnd_global.prog_appl_id,  -1);
129     s_request_id := nvl (fnd_global.conc_request_id, -1);
130 
131     l_stmt_id := 30;
132     -- Get the weight reporting UOM.
133     OPEN get_rep_uom_csr (C_WT_MEASURE_CODE);
134     FETCH get_rep_uom_csr INTO s_wt_rep_uom_code;
135     IF (get_rep_uom_csr%NOTFOUND) THEN
136         s_wt_rep_uom_code := NULL;
137     END IF;
138 
139     CLOSE get_rep_uom_csr;
140 
141     l_stmt_id := 40;
142     -- Get the volume reporting UOM.
143     OPEN get_rep_uom_csr (C_VOL_MEASURE_CODE);
144     FETCH get_rep_uom_csr INTO s_vol_rep_uom_code;
145     IF (get_rep_uom_csr%NOTFOUND) THEN
146         s_vol_rep_uom_code := NULL;
147     END IF;
148 
149     CLOSE get_rep_uom_csr;
150 
151     return;
152 
153 EXCEPTION
154 
155     WHEN SCHEMA_INFO_NOT_FOUND THEN
156 
157         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
158                                             (SCHEMA_INFO_NOT_FOUND_MESG,
159                                              l_proc_name, l_stmt_id));
160         RAISE GLOBAL_SETUP_MISSING;
161 
162 
163     WHEN OTHERS THEN
164         rollback;
165 
166         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
167                                                      l_stmt_id));
168         RAISE GLOBAL_SETUP_MISSING;
169 
170 END global_setup;
171 
172 
173 
174 /*  err_mesg
175 
176     Return a C_ERRBUF_SIZE character long, properly formatted error
177     message with the package name, procedure name and message.
178 
179     Parameters:
180     p_mesg - Actual message to be printed
181     p_proc_name - name of procedure that should be printed in the message
182      (optional)
183     p_stmt_id - step in procedure at which error occurred
184      (optional)
185 
186     History:
187     Date        Author              Action
188     12/08/04    Dinkar Gupta        Defined function.
189 */
190 
191 FUNCTION err_mesg (p_mesg IN VARCHAR2,
192                    p_proc_name IN VARCHAR2,
193                    p_stmt_id IN NUMBER)
194     RETURN VARCHAR2
195 IS
196 
197     l_proc_name CONSTANT VARCHAR2 (60) := 'err_mesg';
198     l_stmt_id NUMBER;
199 
200     -- The variable declaration cannot take C_ERRBUF_SIZE (a defined constant)
201     -- as the size of the declaration. I have to put 300 here.
202     l_formatted_message VARCHAR2 (300);
203 
204 BEGIN
205 
206     -- initialization block
207     l_stmt_id := 0;
208 
209     -- initialization block
210     l_formatted_message := NULL;
211 
212     l_stmt_id := 10;
213     l_formatted_message := substr ((C_PKG_NAME || '.' || p_proc_name || ' #' ||
214                                    to_char (p_stmt_id) || ': ' || p_mesg),
215                                    1, C_ERRBUF_SIZE);
216 
217     commit;
218 
219     return l_formatted_message;
220 
221 EXCEPTION
222 
223     WHEN OTHERS THEN
224         -- the exception happened in the exception reporting function !!
225         -- return with ERROR.
226         l_formatted_message := substr ((C_PKG_NAME || '.' || l_proc_name ||
227                                        ' #' ||
228                                         to_char (l_stmt_id) || ': ' ||
229                                        SQLERRM),
230                                        1, C_ERRBUF_SIZE);
231 
232         l_formatted_message := 'Error in error reporting.';
233         return l_formatted_message;
234 
235 END err_mesg;
236 
237 /*  print_stage_done_mesg
238 
239     Print a message of 'Done' for whatever procedure/statement called.
240 
241     Parameters:
242     p_proc_name - name of procedure that should be printed in the message
243     p_stmt_id - step in procedure at which error occurred
244 
245     History:
246     Date        Author              Action
247     12/13/04    Dinkar Gupta        Defined function.
248 */
249 
250 PROCEDURE print_stage_done_mesg (p_proc_name IN VARCHAR2,
251                                  p_stmt_id IN NUMBER)
252 IS
253 
254     l_proc_name CONSTANT VARCHAR2 (60) := 'print_stage_done_mesg';
255     l_stmt_id NUMBER;
256 
257     -- The variable declaration cannot take C_ERRBUF_SIZE (a defined constant)
258     -- as the size of the declaration. I have to put 300 here.
259     l_formatted_message VARCHAR2 (300);
260 
261 BEGIN
262 
263     -- initialization block
264     l_stmt_id := 0;
265 
266     -- initialization block
267     l_formatted_message := NULL;
268 
269     l_stmt_id := 10;
270     l_formatted_message := substr ((C_PKG_NAME || '.' || p_proc_name || ' #' ||
271                                    to_char (p_stmt_id) || ': ' || 'Done.'),
272                                    1, C_ERRBUF_SIZE);
273 
274     BIS_COLLECTION_UTILITIES.PUT_LINE (l_formatted_message);
275 
276     return;
277 
278 EXCEPTION
279 
280     WHEN OTHERS THEN
281         -- the exception happened in the print function
282         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
283                                                      l_stmt_id));
284 
285         RAISE; -- on to wrapper
286 
287 END print_stage_done_mesg;
288 
289 /*  setup_tables
290 
291     Clean up tables related to the Current Capacity Utilization report.
292     Currently, only need to truncate:
293     1. opi_dbi_wms_curr_utz_sub_stg
294     2. opi_dbi_wms_curr_utz_sub_f
295     1. opi_dbi_wms_curr_utz_item_f
296 
297     History:
298     Date        Author              Action
299     12/08/04    Dinkar Gupta        Wrote Function.
300 */
301 PROCEDURE setup_tables
302 IS
303 
304     l_proc_name CONSTANT VARCHAR2 (40) := 'setup_tables';
305     l_stmt_id NUMBER;
306 
307 BEGIN
308 
309     -- Initialization block
310     l_stmt_id := 0;
311 
312     l_stmt_id := 10;
313     -- Truncate OPI_DBI_WMS_CURR_UTZ_SUB_STG
314     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
315                        'OPI_DBI_WMS_CURR_UTZ_SUB_STG');
316 
317     l_stmt_id := 20;
318     -- Truncate OPI_DBI_WMS_CURR_UTZ_SUB_F
319     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
320                        'OPI_DBI_WMS_CURR_UTZ_SUB_F');
321 
322     l_stmt_id := 30;
323     -- Truncate OPI_DBI_WMS_CURR_UTZ_ITEM_F
324     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
325                        'OPI_DBI_WMS_CURR_UTZ_ITEM_F');
326 
327     return;
328 
329 EXCEPTION
330 
331     WHEN OTHERS THEN
332         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
333                                                      l_stmt_id));
334         RAISE TABLE_SETUP_FAILED;
335 
336 END setup_tables;
337 
338 
339 /*  refresh_current_utilization
340 
341     Wrapper routine to refresh
342     1. The weight/volume capacity of warehouses and their subinventories.
343     2. The weight and volume of items stored currently in the
344        warehouse's locators.
345 
346     Locator capacities:
347     A locator may have a defined max weight and/or max volume capacity.
348     Locators with neither values defined are ignored. Locators with
349     only one of the quantities defined contribute to the corresponding
350     measure for the subinventory to which they belong.
351 
352     Item Weights/volume:
353     The item weight will be taken into account only if the locator
354     it is present in has a defined weight capacity. Similar condition
355     for the item volume. Item quantities present in locators with
356     neither weight nor volume capacity defined are ignored.
357 
358     Errors are reported for all:
359     1. Defined locator weight/volume capacities that cannot be
360        converted to the weight/volume reporting UOM values.
361     2. Defined item weights/volumes that cannot be converted
362        into the weight/volume reporting UOM values.
363 
364     No data is collected for the report in case of errors, and the fact
365     tables are left truncated.
366 
367     Warnings need to be generated for:
368     1. All locators whose unit weight/volume capacities are undefined.
369     2. All items whose unit weight/volume are undefined.
370     Warnings are not generated here for performance reasons mainly.
371     However there is a performance reason for it also, namely that if
372     a user does not set up some item weight/volumes or locator capacities,
373     reporting warnings in this program will always cause termination with
374     warnings. A separate concurrent program will be provided with the
375     explicit task of reporting setup warnings.
376 
377     Parameters:
378         errbuf - error message on unsuccessful termination
379         retcode - 0 on success, 1 on warning, -1 on error
380 
381     History:
382     Date        Author              Action
383     12/08/04    Dinkar Gupta        Wrote Function.
384 */
385 PROCEDURE refresh_current_utilization (errbuf OUT NOCOPY VARCHAR2,
386                                        retcode OUT NOCOPY NUMBER)
387 IS
388 
389     l_proc_name CONSTANT VARCHAR2 (40) := 'refresh_current_utilization';
390     l_stmt_id NUMBER;
391 
392     -- Booleans to track errors
393     l_locator_error BOOLEAN;
394     l_item_error BOOLEAN;
395 
396 BEGIN
397 
398     -- Initialization Block
399     l_stmt_id := 10;
400     l_locator_error := FALSE;
401     l_item_error := FALSE;
402 
403     l_stmt_id := 10;
404     -- Set up the global parameters
405     global_setup ();
406     print_stage_done_mesg (l_proc_name, l_stmt_id);
407 
408     l_stmt_id := 20;
409     -- Set up the relevant tables
410     setup_tables ();
411     print_stage_done_mesg (l_proc_name, l_stmt_id);
412 
413     l_stmt_id := 30;
414     -- Ensure that we only do something if at least one of the
415     -- reporting UOMs is set up. Otherwise just return.
416     IF (s_wt_rep_uom_code IS NULL AND
417         s_vol_rep_uom_code IS NULL) THEN
418         RAISE NO_REP_UOMS_DEFINED;
419     END IF;
420     print_stage_done_mesg (l_proc_name, l_stmt_id);
421 
422     l_stmt_id := 40;
423     -- Capture Locator capacity info into the staging table.
424     -- Errors will be reported off this table for starters.
425     extract_locator_capacities (s_wt_rep_uom_code, s_vol_rep_uom_code);
426     print_stage_done_mesg (l_proc_name, l_stmt_id);
427 
428     l_stmt_id := 50;
429     -- Commit the information inserted into the staging table.
430     commit;
431     print_stage_done_mesg (l_proc_name, l_stmt_id);
432 
433     l_stmt_id := 60;
434     -- Extract all the item level information into the item fact using
435     -- the locator capacities in the staging table to determine if items
436     -- need to be ignored.
437     extract_item_storage (s_wt_rep_uom_code, s_vol_rep_uom_code);
438     print_stage_done_mesg (l_proc_name, l_stmt_id);
439 
440     l_stmt_id := 70;
441     -- Commit all item level information extracted so far.
442     commit;
443     print_stage_done_mesg (l_proc_name, l_stmt_id);
444 
445     l_stmt_id := 80;
446     -- Report errors in reporting UOM conversions for the locator staging
447     -- table. Track if any errors occurred.
448     l_locator_error := check_locator_setup_errors ();
449     print_stage_done_mesg (l_proc_name, l_stmt_id);
450 
451     l_stmt_id := 90;
452     -- Report errors in reporting UOM conversions for the item weight/
453     -- volume in the item fact. Track if any errors occurred.
454     l_item_error := check_item_setup_errors ();
455     print_stage_done_mesg (l_proc_name, l_stmt_id);
456 
457     l_stmt_id := 100;
458     -- If any errors occurred, abort after cleaning out all the tables.
459     IF (l_locator_error OR l_item_error) THEN
460 
461         -- Don't truncate the locator capacity staging table.
462         -- The details in the table can be used for detail locator
463         -- level error reporting in the standalone concurrent program,
464         -- Report Warehouse Storage Utilized/Current Capacity Utilization
465         -- UOM Conversion Rates Error Details.
466         commit;
467 
468         -- exit
469         RAISE PREMATURE_ABORT;
470 
471     END IF;
472     print_stage_done_mesg (l_proc_name, l_stmt_id);
473 
474     l_stmt_id := 110;
475     -- If got here, then no errors have occurred. So move all the
476     -- locator data into the subinventory fact table.
477     summarize_capacities ();
478     print_stage_done_mesg (l_proc_name, l_stmt_id);
479 
480     l_stmt_id := 120;
481     -- Commit all data
482     Commit;
483     print_stage_done_mesg (l_proc_name, l_stmt_id);
484 
485     l_stmt_id := 130;
486     -- Everything successful so commit and truncate the staging table.
487     commit;
488     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
489                        'OPI_DBI_WMS_CURR_UTZ_SUB_STG');
490     print_stage_done_mesg (l_proc_name, l_stmt_id);
491 
492     errbuf := '';
493     retcode := C_SUCCESS;
494     BIS_COLLECTION_UTILITIES.PUT_LINE (C_SUCCESS_MESG);
495     return;
496 
497 EXCEPTION
498 
499     WHEN GLOBAL_SETUP_MISSING THEN
500         rollback;
501         retcode := C_ERROR;
502         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
503 
504         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
505                                             (GLOBAL_SETUP_MISSING_MESG,
506                                              l_proc_name, l_stmt_id));
507         return;
508 
509     WHEN TABLE_SETUP_FAILED THEN
510         rollback;
511         retcode := C_ERROR;
512         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
513 
514         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
515                                             (TABLE_SETUP_FAILED_MESG,
516                                              l_proc_name, l_stmt_id));
517         return;
518 
519     WHEN LOCATOR_CAP_CALC_FAILED THEN
520         rollback;
521         retcode := C_ERROR;
522         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
523 
524         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
525                                             (LOCATOR_CAP_CALC_MESG,
526                                              l_proc_name, l_stmt_id));
527         return;
528 
529     WHEN NO_REP_UOMS_DEFINED THEN
530         rollback;
531         retcode := C_WARNING; -- ??? should this be success?
532         errbuf := C_CURR_UTZ_LOAD_WARN_MESG;
533 
534         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
535                                             (NO_REP_UOMS_DEFINED_MESG,
536                                              l_proc_name, l_stmt_id));
537         return;
538 
539     WHEN PREMATURE_ABORT THEN
540         rollback;
541         retcode := C_ERROR;
542         errbuf := C_CURR_UTZ_LOAD_WARN_MESG;
543 
544         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
545                                             (PREMATURE_ABORT_MESG,
546                                              l_proc_name, l_stmt_id));
547         return;
548 
549     WHEN ITEM_STOR_CALC_FAILED THEN
550         rollback;
551         retcode := C_ERROR;
552         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
553 
554         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
555                                             (ITEM_STOR_CALC_FAILED_MESG,
556                                              l_proc_name, l_stmt_id));
557         return;
558 
559     WHEN LOCATOR_ERR_CHECK_FAILED THEN
560         rollback;
561         retcode := C_ERROR;
562         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
563 
564         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
565                                             (LOCATOR_ERR_CHECK_FAILED_MESG,
566                                              l_proc_name, l_stmt_id));
567         return;
568 
569     WHEN ITEM_ERR_CHECK_FAILED THEN
570         rollback;
571         retcode := C_ERROR;
572         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
573 
574         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
575                                             (ITEM_ERR_CHECK_FAILED_MESG,
576                                              l_proc_name, l_stmt_id));
577         return;
578 
579     WHEN OTHERS THEN
580         rollback;
581         retcode := C_ERROR;
582         errbuf := C_CURR_UTZ_LOAD_ERROR_MESG;
583 
584         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
585                                                      l_stmt_id));
586 
587         return;
588 
589 END refresh_current_utilization;
590 
591 
592 /**************************************************
593  * Warehouse Capacity Related procedures
594  **************************************************/
595 
596 /*  extract_locator_capacities
597 
598     Extract the locator weight and volume capacities in the
599     staging table, OPI_DBI_WMS_CURR_UTZ_SUB_STG. The capacities
600     should be stored in the reporting units of the measures.
601     If the weight or volume capacity is null, store NULL.
602     If the conversion is not defined in the reporting UOM table,
603     OPI_DBI_REP_UOM_STD_CONV_F, store -1.
604 
605     Note also that one or both of the reporting units for weight
606     and volume can be NULL. That is not an error condition.
607 
608     No committing of data here. The calling function handles that.
609 
610     Parameters:
611     1. p_wt_rep_uom_code - Weight reporting UOM code
612     2. p_vol_rep_uom_code - Volume reporting UOM code
613 
614     History:
615     Date        Author              Action
616     12/08/04    Dinkar Gupta        Wrote Function.
617 
618 */
619 PROCEDURE extract_locator_capacities (p_wt_rep_uom_code IN VARCHAR2,
620                                       p_vol_rep_uom_code IN VARCHAR2)
621 IS
622     l_proc_name CONSTANT VARCHAR2 (40) := 'extract_locator_capacities';
623     l_stmt_id NUMBER;
624 
625     -- local copy of reporting UOMs
626     l_wt_rep_uom_code VARCHAR2 (3);
627     l_vol_rep_uom_code VARCHAR2 (3);
628 
629 BEGIN
630 
631     -- Initialization block
632     l_stmt_id := 0;
633     l_wt_rep_uom_code := NULL;
634     l_vol_rep_uom_code := NULL;
635 
636     l_stmt_id := 10;
637     -- If both reporting UOMs are undefined, return. Wrapper routine
638     -- should ensure this doesn't happen, but check just in case.
639     IF (p_wt_rep_uom_code IS NULL AND
640         p_vol_rep_uom_code IS NULL) THEN
641         RAISE NO_REP_UOMS_DEFINED;
642     END IF;
643 
644     l_stmt_id := 20;
645     -- Set the reporting UOM's to the dummy code, to avoid handling
646     -- the condition that one of them can be NULL in the SQL below.
647     l_wt_rep_uom_code := nvl (p_wt_rep_uom_code, C_DUMMY_UOM_CODE);
648     l_vol_rep_uom_code := nvl (p_vol_rep_uom_code, C_DUMMY_UOM_CODE);
649 
650     l_stmt_id := 30;
651     -- Compute the weight/volume capacities for locators in warehouse
652     -- enabled organizations. No need to specifically filter out
653     -- process organizations since their locator setup is not
654     -- stored in MTL_ITEM_LOCATIONS.
655     --
656     -- The locator weight capacity, volume_capacity, weight_uom_code
657     -- and volume_uom_code are stored in the MTL_ITEM_LOCATIONS table.
658     --
659     -- All possible conversions to the reporting UOMs are stored in
660     -- the standard conversion rates table, OPI_DBI_REP_UOM_STD_CONV_F.
661     -- The extraction program will join twice to this table, once
662     -- for weight capacity conversions and once for volume capacity
663     -- conversions. Since certain rows may not join to the conversion
664     -- fact for one of the measures, use outer joins.
665     --
666     -- The following are possible pathological scenarios:
667     --
668     -- Capacity Setups:
669     -- 1. Locator Weight capacity (value or UOM) might be missing.
670     -- 2. Locator Volume capacity (value or UOM) might be missing.
671     -- Either of the two above are not cause for error, and the corresponding
672     -- capacity should be stored as NULL.
673     -- The above conditions are detectable as the value of max_weight
674     -- and max_cubic_area in MTL_ITEM_LOCATIONS will be NULL if the setup
675     -- is missing.
676     --
677     -- If both capacities are NULL, then for conciseness don't store a
678     -- row for that locator.
679     --
680     -- Missing Conversions:
681     -- 1. Locator Weight capacity conversion to reporting weight UOM is
682     --    invalid.
683     -- 2. Locator Volume capacity conversion to reporting weight UOM is
684     --    invalid.
685     -- Either of the two above are error conditions and the corresponding
686     -- capacities must therefore be flagged with a -1 so that it can be
687     -- reported.
688     -- The above conditions are detectable as the corresponding conversion
689     -- rates will be negative in the standard conversion rates table,
690     -- OPI_DBI_REP_UOM_STD_CONV_F.
691     --
692     -- Missing Reporting UOMs:
693     -- 1. The Weight Reporting UOM can be missing.
694     -- 2. The Volume Reporting UOM can be missing.
695     -- Since both won't be missing, these are acceptable scenarios i.e.
696     -- ones where customers do not care about one of the measures. Simply
697     -- set that measure to NULL everywhere.
698     --
699     -- Weight/Volume UOM can be the same:
700     -- 1. The locator's weight capacity and volume capacity UOM can be the
701     --    same. This is acceptable. However, suppose this UOM is Kg, that
702     --    needs to be converted to weight reporting UOM (lbs) and volume
703     --    reporting UOM M3.
704     --    Say the conversion rates table has a rate from Kg --> lbs, but
705     --    nothing from Kg --> M3. To avoid filtering out rows for such
706     --    locators and instead reporting errors for them, this SQL has
707     --    to be written with an inline view which contains all the
708     --    from and reporting UOMs, and an outer SQL that purely outer
709     --    joins to the standard conversion rates tables based on these
710     --    from and reporting UOMs.
711     --
712     INSERT /*+ append */
713     INTO opi_dbi_wms_curr_utz_sub_stg (
714         organization_id,
715         subinventory_code,
716         locator_id,
717         weight_capacity_b,
718         weight_uom_code,
719         weight_capacity_rep,
720         volume_capacity_b,
721         volume_uom_code,
722         volume_capacity_rep)
723     SELECT /*+ parallel (loc) parallel (wt_conv) parallel (vol_conv)
724                use_hash (loc, wt_conv, vol_conv) */
725         loc.organization_id,
726         loc.subinventory_code,
727         loc.locator_id,
728         loc.max_weight weight_capacity_b,
729         decode (loc.weight_uom_code,
730                 C_DUMMY_UOM_CODE, NULL,
731                 loc.weight_uom_code) weight_uom_code,
732         CASE  -- the order of conditions matters
733             WHEN loc.max_weight IS NULL THEN
734                 -- Weight capacity is not setup up. Legitimate NULL case.
735                 NULL
736             WHEN loc.wt_rep_uom_code = C_DUMMY_UOM_CODE THEN
737                 --  No weight reporting UOM defined. Acceptable.
738                 NULL
739             WHEN loc.weight_uom_code = C_DUMMY_UOM_CODE AND
740                  loc.max_weight IS NOT NULL THEN
741                 -- Setup error. Value defined, but no UOM.
742                 -- Ignore this locator.
743                 NULL
744             WHEN wt_conv.conversion_rate IS NULL THEN
745                 -- Row created from pure outer join i.e. it is a valid
746                 -- combination with non-null UOMs and there is
747                 -- no conv. rate for this combination.
748                 -- From_uom_code and rep_uom_code
749                 -- will be null in the wt_conv table for this row also.
750                 C_CONV_NOT_SETUP
751             WHEN wt_conv.conversion_rate < 0 THEN
752                 -- Error found in conversion rates table.
753                 C_CONV_NOT_SETUP
754             WHEN wt_conv.conversion_rate >= 0 THEN
755                 -- Valid conv. rate found.
756                 -- Note: allowing conv. rate = 0.
757                 loc.max_weight * wt_conv.conversion_rate
758             ELSE
759                 -- Why will we get here? Should really never.
760                 C_CONV_NOT_SETUP
761         END weight_capacity_rep,
762         loc.max_cubic_area volume_capacity_b,
763         decode (loc.volume_uom_code,
764                 C_DUMMY_UOM_CODE, NULL,
765                 loc.volume_uom_code) volume_uom_code,
766         CASE  -- the order of conditions matters
767             WHEN loc.max_cubic_area IS NULL THEN
768                 -- Volume capacity is not setup up. Legitimate NULL case.
769                 NULL
770             WHEN loc.vol_rep_uom_code = C_DUMMY_UOM_CODE THEN
771                 --  No volume reporting UOM defined. Acceptable.
772                 NULL
773             WHEN loc.volume_uom_code = C_DUMMY_UOM_CODE AND
774                  loc.max_cubic_area IS NOT NULL THEN
775                 -- Setup error. Value defined, but no UOM.
776                 -- Ignore this locator.
777                 NULL
778             WHEN vol_conv.conversion_rate IS NULL THEN
779                 -- Row created from pure outer join i.e. it is a valid
780                 -- combination with non-null UOMs and there is
781                 -- no conv. rate for this combination.
782                 -- From_uom_code and rep_uom_code
783                 -- will be null in the vol_conv table for this row also.
784                 C_CONV_NOT_SETUP
785             WHEN vol_conv.conversion_rate < 0 THEN
786                 -- Error found in conversion rates table.
787                 C_CONV_NOT_SETUP
788             WHEN vol_conv.conversion_rate >= 0 THEN
789                 -- Valid conv. rate found.
790                 -- Note: allowing conv. rate = 0.
791                 loc.max_cubic_area * vol_conv.conversion_rate
792             ELSE
793                 -- Why will we get here? Should really never.
794                 C_CONV_NOT_SETUP
795         END volume_capacity_rep
796       FROM
797         (SELECT /*+ parallel (mil) parallel (mp) */
798             mil.organization_id,
799             mil.subinventory_code,
800             mil.inventory_location_id locator_id,
801             mil.max_weight max_weight,
802             mil.max_cubic_area max_cubic_area,
803             nvl (mil.location_weight_uom_code,
804                  C_DUMMY_UOM_CODE) weight_uom_code,
805             l_wt_rep_uom_code wt_rep_uom_code,
806             nvl (mil.volume_uom_code, C_DUMMY_UOM_CODE) volume_uom_code,
807             l_vol_rep_uom_code vol_rep_uom_code
808           FROM  mtl_item_locations mil,
809                 mtl_parameters mp
810           WHERE mp.wms_enabled_flag = 'Y'
811             AND mil.organization_id = mp.organization_id
812             -- filter out locators with neither capacity defined
813             AND (   (    mil.max_weight IS NOT NULL
814                      AND mil.location_weight_uom_code IS NOT NULL)
815                  OR (    mil.max_cubic_area IS NOT NULL
816                      AND mil.volume_uom_code IS NOT NULL)
817                 )
818         ) loc,
819         opi_dbi_rep_uom_std_conv_f wt_conv,
820         opi_dbi_rep_uom_std_conv_f vol_conv
821       WHERE loc.weight_uom_code = wt_conv.from_uom_code (+)
822         AND loc.wt_rep_uom_code = wt_conv.rep_uom_code (+)
823         AND loc.volume_uom_code = vol_conv.from_uom_code (+)
824         AND loc.vol_rep_uom_code = vol_conv.rep_uom_code (+);
825 
826     return;
827 
828 EXCEPTION
829 
830     -- Just report this in the wrapper. Shouldn't happen ever anyway.
831     WHEN NO_REP_UOMS_DEFINED THEN
832         RAISE;
833 
834     WHEN OTHERS THEN
835         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
836                                                      l_stmt_id));
837         RAISE LOCATOR_CAP_CALC_FAILED;
838 
839 END extract_locator_capacities;
840 
841 
842 /*  Summarize_capacities
843 
844     Summarize the locator capacities to the subinventory and organization
845     levels (much like a nested MV without the time dimension).
846     The capacities summarized are in the reporting UOMs of the
847     respective measures
848 
849     The aggregation levels (in keeping with the values used in other
850     MVs etc):
851     7 - Organization level records
852     1 - Subinventory level records
853 
854     No committing of data here. The calling function handles that.
855 
856     History:
857     Date        Author              Action
858     12/08/04    Dinkar Gupta        Wrote Function.
859 
860 */
861 PROCEDURE summarize_capacities
862 IS
863 
864     l_proc_name CONSTANT VARCHAR2 (40) := 'summarize_capacities';
865     l_stmt_id NUMBER;
866 
867 BEGIN
868 
869     -- Initialization block
870     l_stmt_id := 0;
871 
872     l_stmt_id := 10;
873     -- Summarize the reporting UOM weight and volume capacity values
874     -- stored in the staging table. Since the report needs to run
875     -- only at the subinventory and organization levels, aggregate the
876     -- data. The extra cost of aggregating to the organization level is
877     -- minimal.
878     --
879     -- It is assumed that the data can simply be aggregated. Any errors
880     -- that were recorded as negative capacities have been handled/
881     -- resolved already (or this function is not called when such errors
882     -- exist).
883     INSERT /*+ append */
884     INTO opi_dbi_wms_curr_utz_sub_f (
885         organization_id,
886         subinventory_code,
887         aggregation_level_flag,
888         weight_capacity,
889         volume_capacity,
890         creation_date,
891         last_update_date,
892         created_by,
893         last_updated_by,
894         last_update_login,
895         program_id,
896         program_login_id,
897         program_application_id,
898         request_id
899     )
900     SELECT /*+ parallel (stg) */
901         stg.organization_id,
902         decode (stg.subinventory_code,
903                 NULL, NULL,
904                 stg.subinventory_code || '-' || stg.organization_id)
905           subinventory_code,
906         decode (grouping_id (stg.organization_id,
907                              decode (stg.subinventory_code,
908                                      NULL, NULL,
909                                      stg.subinventory_code || '-' ||
910                                      stg.organization_id)),
911                 0, 1,
912                 1, 7,
913                 -1) aggregation_level_flag,
914         sum (stg.weight_capacity_rep) weight_capacity_rep,
915         sum (stg.volume_capacity_rep) volume_capacity_rep,
916         sysdate,
917         sysdate,
918         s_user_id,
919         s_user_id,
920         s_login_id,
921         s_program_id,
922         s_program_login_id,
923         s_program_application_id,
924         s_request_id
925       FROM opi_dbi_wms_curr_utz_sub_stg stg
926       GROUP BY
927         stg.organization_id,
928         rollup (decode (stg.subinventory_code,
929                         NULL, NULL,
930                         stg.subinventory_code || '-' || stg.organization_id));
931 
932 
933     return;
934 
935 EXCEPTION
936 
937     WHEN OTHERS THEN
938         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
939                                                      l_stmt_id));
940         RAISE SUMMARIZE_CAP_FAILED;
941 
942 END summarize_capacities;
943 
944 /*  check_locator_setup_errors
945 
946     Report any invalid conversion rates found for locator weight
947     and or volume capacities.
948 
949     History:
950     Date        Author              Action
951     12/30/04    Dinkar Gupta        Wrote Function.
952 
953 */
954 FUNCTION check_locator_setup_errors
955     RETURN BOOLEAN
956 
957 IS
958 
959     l_proc_name CONSTANT VARCHAR2 (40) := 'check_locator_setup_errors';
960     l_stmt_id NUMBER;
961 
962     -- check if the header has been printed
963     l_header_printed BOOLEAN;
964 
965     -- check whether to return errors
966     l_errors BOOLEAN;
967 
968     -- Cursor for missing weight conversions.
969     CURSOR wt_missing_rates_csr IS
970     SELECT DISTINCT
971         weight_uom_code uom_code
972       FROM opi_dbi_wms_curr_utz_sub_stg
973       WHERE weight_capacity_rep < 0;
974 
975     -- Cursor for missing volume conversions.
976     CURSOR vol_missing_rates_csr IS
977     SELECT DISTINCT
978         volume_uom_code uom_code
979       FROM opi_dbi_wms_curr_utz_sub_stg
980       WHERE volume_capacity_rep < 0;
981 
982 BEGIN
983 
984     -- Initialization block
985     l_errors := FALSE;      -- no errors yet
986     l_header_printed := FALSE;
987     l_stmt_id := 0;
988 
989     -- Report missing weights.
990     l_header_printed := FALSE;
991     l_stmt_id := 10;
992     FOR wt_missing_rates_rec IN wt_missing_rates_csr
993     LOOP
994 
995         -- Print the header once if not done so yet.
996         l_stmt_id := 20;
997         IF (l_header_printed = FALSE) THEN
998 
999             OPI_DBI_REP_UOM_PKG.err_msg_header_spec ('WT', 'LOC');
1000             l_header_printed := TRUE;
1001 
1002         END IF;
1003 
1004         -- Print the missing rates.
1005         l_stmt_id := 30;
1006         OPI_DBI_REP_UOM_PKG.err_msg_missing_uoms (
1007             wt_missing_rates_rec.uom_code, s_wt_rep_uom_code);
1008 
1009         -- There is an error to report
1010         l_stmt_id := 40;
1011         l_errors := TRUE;
1012 
1013     END LOOP;
1014 
1015     -- Footer message.
1016     IF (l_header_printed = TRUE) THEN
1017         OPI_DBI_REP_UOM_PKG.err_msg_footer;
1018     END IF;
1019 
1020     -- Report missing weights.
1021     l_header_printed := FALSE;
1022     l_stmt_id := 50;
1023     FOR vol_missing_rates_rec IN vol_missing_rates_csr
1024     LOOP
1025 
1026         -- Print the header once if not done so yet.
1027         l_stmt_id := 60;
1028         IF (l_header_printed = FALSE) THEN
1029 
1030             OPI_DBI_REP_UOM_PKG.err_msg_header_spec ('VOL', 'LOC');
1031             l_header_printed := TRUE;
1032 
1033         END IF;
1034 
1035         -- Print the missing rates.
1036         l_stmt_id := 70;
1037         OPI_DBI_REP_UOM_PKG.err_msg_missing_uoms (
1038             vol_missing_rates_rec.uom_code, s_vol_rep_uom_code);
1039 
1040         -- There is an error to report
1041         l_stmt_id := 80;
1042         l_errors := TRUE;
1043 
1044     END LOOP;
1045 
1046     -- Footer message.
1047     IF (l_header_printed = TRUE) THEN
1048         OPI_DBI_REP_UOM_PKG.err_msg_footer;
1049     END IF;
1050 
1051     return l_errors;
1052 
1053 EXCEPTION
1054 
1055     WHEN OTHERS THEN
1056         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1057                                                      l_stmt_id));
1058         RAISE LOCATOR_ERR_CHECK_FAILED;
1059 
1060 END check_locator_setup_errors;
1061 
1062 
1063 /**************************************************
1064  * Item Storage Related procedures
1065  **************************************************/
1066 
1067 /*  extract_locator_capacities
1068 
1069     Extract the item storage in all locators of warehouses that
1070     have weight and/or volume capacities defined. The locator
1071     capacities are stored in the locator staging table,
1072     OPI_DBI_WMS_CURR_UTZ_SUB_STG. The item weights/volumes must
1073     be stored in the reporting UOM values. If a locator does
1074     not have weight capacity defined the item's weight in that
1075     locator is ignored. Same goes for the item volume. If the
1076     conversion rate for the weight/volume to the reporting UOMs
1077     is not defined, store negative error codes.
1078 
1079 
1080 
1081     Note also that one or both of the reporting units for weight
1082     and volume can be NULL. That is not an error condition.
1083 
1084     No committing of data here. The calling function handles that.
1085 
1086     Parameters:
1087     1. p_wt_rep_uom_code - Weight reporting UOM code
1088     2. p_vol_rep_uom_code - Volume reporting UOM code
1089 
1090     History:
1091     Date        Author              Action
1092     12/08/04    Dinkar Gupta        Wrote Function.
1093 
1094 */
1095 PROCEDURE extract_item_storage (p_wt_rep_uom_code IN VARCHAR2,
1096                                 p_vol_rep_uom_code IN VARCHAR2)
1097 
1098 IS
1099     l_proc_name CONSTANT VARCHAR2 (40) := 'extract_item_storage';
1100     l_stmt_id NUMBER;
1101 
1102     -- local copy of reporting UOMs
1103     l_wt_rep_uom_code VARCHAR2 (3);
1104     l_vol_rep_uom_code VARCHAR2 (3);
1105 
1106 BEGIN
1107 
1108     -- initialization block
1109     l_stmt_id := 0;
1110     l_wt_rep_uom_code := NULL;
1111     l_vol_rep_uom_code := NULL;
1112 
1113     l_stmt_id := 10;
1114     -- If both reporting UOMs are undefined, return. Wrapper routine
1115     -- should ensure this doesn't happen, but check just in case.
1116     IF (p_wt_rep_uom_code IS NULL AND
1117         p_vol_rep_uom_code IS NULL) THEN
1118         RAISE NO_REP_UOMS_DEFINED;
1119     END IF;
1120 
1121     l_stmt_id := 20;
1122     -- Set the reporting UOM's to the dummy code, to avoid handling
1123     -- the condition that one of them can be NULL in the SQL below.
1124     l_wt_rep_uom_code := nvl (p_wt_rep_uom_code, C_DUMMY_UOM_CODE);
1125     l_vol_rep_uom_code := nvl (p_vol_rep_uom_code, C_DUMMY_UOM_CODE);
1126 
1127     l_stmt_id := 30;
1128     -- Extract the item storage details for all organizations that are
1129     -- WMS enabled. No need to specifically filter out
1130     -- process organizations since their locator setup is not
1131     -- stored in MTL_ONHAND_QUANTITIES.
1132     --
1133     -- Collecting 3 measures:
1134     -- 1. Quantity stored in any locator with weight or volume capacity
1135     --    defined.
1136     -- 2. Weight stored in all locators with weight capacity defined.
1137     -- 3. Volume stored in all locators with volume capacity defined.
1138     --
1139     -- The item setup form guarantees that a UOM be specified for the
1140     -- item weight/volume before a value is specified. So no need to
1141     -- worry about missing UOMs and specified values.
1142     --
1143     -- The subinventory capacity staging table, OPI_DBI_WMS_CURR_UTZ_SUB_STG,
1144     -- has all the locator level records. Use the values in the reporting
1145     -- UOM value columns of the staging table. NULL values in those
1146     -- columns indicate that the corresponding capacity was not specified
1147     -- for the measure on that locator.
1148     --
1149     -- For efficient report query retrieval, store the
1150     -- the data aggregated at the following levels, marked by the
1151     -- following aggregation level flag values:
1152     -- 7 - Organization
1153     -- 1 - Organization, Inventory Category, Subinventory
1154     -- 0 - Organization, Inventory Category, Subinventory, Item
1155     --
1156     -- All possible conversions to the reporting UOMs are stored in
1157     -- the standard conversion rates table, OPI_DBI_REP_UOM_STD_CONV_F.
1158     -- The extraction program will join twice to this table, once
1159     -- for weight capacity conversions and once for volume capacity
1160     -- conversions. Since certain rows may not join to the conversion
1161     -- fact for one of the measures, use outer joins.
1162     --
1163     -- The following pathalogical scenarios are possible:
1164     --
1165     -- Missing Setups:
1166     -- 1. Item Weight setup is missing.
1167     -- 2. Item Volume setup is missing.
1168     -- Either or both of the above are acceptable. In case of no setup,
1169     -- report NULL for the corresponding measure, and report a quantity
1170     -- for the item.
1171     --
1172     -- Missing locator setup:
1173     -- 1. Locator is missing weight capacity.
1174     -- 2. Locator is missing volume capacity.
1175     -- By design, both of the above conditions cannot be simultaneously true.
1176     -- Ignore the item's contribution to the measure whose capacity setup
1177     -- is missing on the locator by recording a NULL value.
1178     --
1179     -- Missing conversion rates:
1180     -- 1. Item weight cannot be converted into the reporting weight UOM.
1181     -- 2. Item volume cannot be converted into the reporting volume UOM.
1182     -- This will be recorded as a negative number, given the negative
1183     -- error codes for missing rates. Store that for the moment, and
1184     -- report errors later. If no conversion rate is found, record a
1185     -- negative number.
1186     --
1187     -- Missing Reporting UOMs:
1188     -- 1. The Weight Reporting UOM can be missing.
1189     -- 2. The Volume Reporting UOM can be missing.
1190     -- Since both won't be missing, these are acceptable scenarios i.e.
1191     -- ones where customers do not care about one of the measures. Simply
1192     -- set that measure to NULL everywhere.
1193     --
1194     -- Weight/Volume UOM can be the same:
1195     -- 1. The item's weight capacity and volume UOM can be the
1196     --    same. This is acceptable. However, suppose this UOM is Kg, that
1197     --    needs to be converted to weight reporting UOM (lbs) and volume
1198     --    reporting UOM M3.
1199     --    Say the conversion rates table has a rate from Kg --> lbs, but
1200     --    nothing from Kg --> M3. To avoid filtering out rows for such
1201     --    items and instead reporting errors for them, this SQL has
1202     --    to be written with an inline view which contains all the
1203     --    from and reporting UOMs, and an outer SQL that purely outer
1204     --    joins to the standard conversion rates tables based on these
1205     --    from and reporting UOMs.
1206     --
1207     INSERT /*+ append */
1208     INTO opi_dbi_wms_curr_utz_item_f (
1209         organization_id,
1210         item_org_id,
1211         uom_code,
1212         subinventory_code,
1213         inv_category_id,
1214         aggregation_level_flag,
1215         stored_qty,
1216         weight_qty,
1217         stored_weight,
1218         weight_uom_code,
1219         volume_qty,
1220         utilized_volume,
1221         volume_uom_code,
1222         creation_date,
1223         last_update_date,
1224         created_by,
1225         last_updated_by,
1226         last_update_login,
1227         program_id,
1228         program_login_id,
1229         program_application_id,
1230         request_id)
1231     SELECT /*+ parallel (onh) parallel (wt_conv) parallel (vol_conv)
1232                use_hash (onh, wt_conv, vol_conv) */
1233         onh.organization_id,
1234         (onh.inventory_item_id || '-' || onh.organization_id)
1235           item_org_id,
1236         onh.primary_uom_code uom_code,
1237         decode (onh.subinventory_code,
1238                 NULL, NULL,
1239                 (onh.subinventory_code || '-' || onh.organization_id))
1240           subinventory_code,
1241         nvl (onh.inv_category_id, -1) inv_category_id,
1242         grouping_id (onh.organization_id,
1243                      nvl (onh.inv_category_id, -1),
1244                      decode (onh.subinventory_code,
1245                              NULL, NULL,
1246                              (onh.subinventory_code || '-' ||
1247                               onh.organization_id)),
1248                      (onh.inventory_item_id || '-' ||
1249                       onh.organization_id))
1250           aggregation_level_flag,
1251         sum (onh.stored_qty) stored_qty,
1252         sum (onh.weight_qty) weight_qty,
1253         sum (
1254             CASE    -- order of conditions matters
1255                 WHEN onh.unit_weight IS NULL THEN
1256                     -- Weight not setup. Acceptable.
1257                     NULL
1258                 WHEN onh.wt_rep_uom_code = C_DUMMY_UOM_CODE THEN
1259                     -- Weight reporting UOM not set up. Acceptable
1260                     NULL
1261                 WHEN wt_conv.conversion_rate IS NULL THEN
1262                     -- Row created from pure outer join i.e. it is a valid
1263                     -- combination with non-null UOMs and there is
1264                     -- no conv. rate for this combination.
1265                     -- From_uom_code and rep_uom_code
1266                     -- will be null in the wt_conv table for this row also.
1267                     C_CONV_NOT_SETUP
1268                 WHEN wt_conv.conversion_rate < 0 THEN
1269                     -- Error found in conversion rates table.
1270                     C_CONV_NOT_SETUP
1271                 WHEN wt_conv.conversion_rate >= 0 THEN
1272                     -- Valid conv. rate found.
1273                     -- Note: allowing conv. rate = 0.
1274                     onh.weight_qty * wt_conv.conversion_rate *
1275                     onh.unit_weight
1276                 ELSE
1277                     -- Why will we get here? Should really never.
1278                     C_CONV_NOT_SETUP
1279             END
1280             ) stored_weight,
1281         onh.weight_uom_code,
1282         sum (onh.volume_qty) volume_qty,
1283         sum (
1284             CASE    -- order of conditions matters
1285                 WHEN onh.unit_volume IS NULL THEN
1286                     -- Volume not setup. Acceptable.
1287                     NULL
1288                 WHEN onh.vol_rep_uom_code = C_DUMMY_UOM_CODE THEN
1289                     -- Volume reporting UOM not set up. Acceptable
1290                     NULL
1291                 WHEN vol_conv.conversion_rate IS NULL THEN
1292                     -- Row created from pure outer join i.e. it is a valid
1293                     -- combination with non-null UOMs and there is
1294                     -- no conv. rate for this combination.
1295                     -- From_uom_code and rep_uom_code
1296                     -- will be null in the vol_conv table for this row also.
1297                     C_CONV_NOT_SETUP
1298                 WHEN vol_conv.conversion_rate < 0 THEN
1299                     -- Error found in conversion rates table.
1300                     C_CONV_NOT_SETUP
1301                 WHEN vol_conv.conversion_rate >= 0 THEN
1302                     -- Valid conv. rate found.
1303                     -- Note: allowing conv. rate = 0.
1304                     onh.volume_qty * vol_conv.conversion_rate *
1305                     onh.unit_volume
1306                 ELSE
1307                     -- Why will we get here? Should really never.
1308                     C_CONV_NOT_SETUP
1309             END
1310             ) utilized_volume,
1311         onh.volume_uom_code,
1312         sysdate,
1313         sysdate,
1314         s_user_id,
1315         s_user_id,
1316         s_login_id,
1317         s_program_id,
1318         s_program_login_id,
1319         s_program_application_id,
1320         s_request_id
1321       FROM
1322         (SELECT /*+ parallel (moq) parallel (mp) parallel (loc)
1323                     parallel (items) */
1324             moq.organization_id,
1325             moq.inventory_item_id,
1326             items.primary_uom_code,
1327             moq.subinventory_code,
1328             nvl (items.weight_uom_code, C_DUMMY_UOM_CODE) weight_uom_code,
1329             l_wt_rep_uom_code wt_rep_uom_code,
1330             nvl (items.volume_uom_code, C_DUMMY_UOM_CODE) volume_uom_code,
1331             l_vol_rep_uom_code vol_rep_uom_code,
1332             items.inv_category_id,
1333             items.unit_weight,
1334             items.unit_volume,
1335             sum (moq.transaction_quantity) stored_qty,
1336             sum (decode (weight_capacity_rep,
1337                          NULL, NULL,
1338                          moq.transaction_quantity)) weight_qty,
1339             sum (decode (volume_capacity_rep,
1340                          NULL, NULL,
1341                          moq.transaction_quantity)) volume_qty
1342           FROM
1343             mtl_onhand_quantities moq,
1344             mtl_parameters mp,
1345             opi_dbi_wms_curr_utz_sub_stg loc,
1346             eni_oltp_item_star items
1347           WHERE mp.wms_enabled_flag = 'Y'
1348             AND moq.organization_id = mp.organization_id
1349             AND moq.organization_id = items.organization_id
1350             AND moq.inventory_item_id = items.inventory_item_id
1351             AND moq.organization_id = loc.organization_id
1352             AND moq.subinventory_code = loc.subinventory_code
1353             AND moq.locator_id = loc.locator_id
1354           GROUP BY
1355             moq.organization_id,
1356             moq.inventory_item_id,
1357             items.primary_uom_code,
1358             moq.subinventory_code,
1359             nvl (items.weight_uom_code, C_DUMMY_UOM_CODE),
1360             nvl (items.volume_uom_code, C_DUMMY_UOM_CODE),
1361             items.inv_category_id,
1362             items.unit_weight,
1363             items.unit_volume
1364         ) onh,
1365         opi_dbi_rep_uom_std_conv_f wt_conv,
1366         opi_dbi_rep_uom_std_conv_f vol_conv
1367       WHERE onh.weight_uom_code = wt_conv.from_uom_code (+)
1368         AND onh.wt_rep_uom_code = wt_conv.rep_uom_code (+)
1369         AND onh.volume_uom_code = vol_conv.from_uom_code (+)
1370         AND onh.vol_rep_uom_code = vol_conv.rep_uom_code (+)
1371       GROUP BY
1372         onh.organization_id,
1373         rollup ( (nvl (onh.inv_category_id, -1),
1374                   decode (onh.subinventory_code,
1375                           NULL, NULL,
1376                           (onh.subinventory_code || '-' ||
1377                            onh.organization_id))),
1378                  ((onh.inventory_item_id || '-' ||
1379                    onh.organization_id),
1380                   onh.primary_uom_code,
1381                   onh.weight_uom_code,
1382                   onh.volume_uom_code) );
1383 
1384     return;
1385 
1386 EXCEPTION
1387 
1388     -- Just report this in the wrapper. Shouldn't happen ever anyway.
1389     WHEN NO_REP_UOMS_DEFINED THEN
1390         RAISE;
1391 
1392     WHEN OTHERS THEN
1393         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1394                                                      l_stmt_id));
1395         RAISE ITEM_STOR_CALC_FAILED;
1396 
1397 END extract_item_storage;
1398 
1399 /*  check_item_setup_errors
1400 
1401     Report any invalid conversion rates found for item weight
1402     and or volume storage.
1403 
1404     History:
1405     Date        Author              Action
1406     12/30/04    Dinkar Gupta        Wrote Function.
1407 
1408 */
1409 FUNCTION check_item_setup_errors
1410     RETURN BOOLEAN
1411 
1412 IS
1413 
1414     l_proc_name CONSTANT VARCHAR2 (40) := 'check_item_setup_errors';
1415     l_stmt_id NUMBER;
1416 
1417     -- check if the header has been printed
1418     l_header_printed BOOLEAN;
1419 
1420     -- check whether to return errors
1421     l_errors BOOLEAN;
1422 
1423     -- Cursor for missing weight conversions at the non-aggregated levels.
1424     -- Use the fact the the quantity and weight should have the same
1425     -- sign.
1426     CURSOR wt_missing_rates_csr IS
1427     SELECT DISTINCT
1428         weight_uom_code uom_code
1429       FROM opi_dbi_wms_curr_utz_item_f
1430       WHERE stored_weight/weight_qty < 0
1431         AND aggregation_level_flag = 0;
1432 
1433     -- Cursor for missing volume conversions at the non-aggregated levels.
1434     -- Use the fact the the quantity and volume should have the same
1435     -- sign.
1436     CURSOR vol_missing_rates_csr IS
1437     SELECT DISTINCT
1438         volume_uom_code uom_code
1439       FROM opi_dbi_wms_curr_utz_item_f
1440       WHERE utilized_volume/volume_qty < 0
1441         AND aggregation_level_flag = 0;
1442 
1443 BEGIN
1444 
1445     -- Initialization block
1446     l_errors := FALSE;      -- no errors yet
1447     l_header_printed := FALSE;
1448     l_stmt_id := 0;
1449 
1450     -- Report missing weights.
1451     l_header_printed := FALSE;
1452     l_stmt_id := 10;
1453     FOR wt_missing_rates_rec IN wt_missing_rates_csr
1454     LOOP
1455 
1456         -- Print the header once if not done so yet.
1457         l_stmt_id := 20;
1458         IF (l_header_printed = FALSE) THEN
1459 
1460             OPI_DBI_REP_UOM_PKG.err_msg_header_spec ('WT', 'ITEM');
1461             l_header_printed := TRUE;
1462 
1463         END IF;
1464 
1465         -- Print the missing rates.
1466         l_stmt_id := 30;
1467         OPI_DBI_REP_UOM_PKG.err_msg_missing_uoms (
1468             wt_missing_rates_rec.uom_code, s_wt_rep_uom_code);
1469 
1470         -- There is an error to report
1471         l_stmt_id := 40;
1472         l_errors := TRUE;
1473 
1474     END LOOP;
1475 
1476     -- Footer message.
1477     IF (l_header_printed = TRUE) THEN
1478         OPI_DBI_REP_UOM_PKG.err_msg_footer;
1479     END IF;
1480 
1481     -- Report missing weights.
1482     l_header_printed := FALSE;
1483     l_stmt_id := 50;
1484     FOR vol_missing_rates_rec IN vol_missing_rates_csr
1485     LOOP
1486 
1487         -- Print the header once if not done so yet.
1488         l_stmt_id := 60;
1489         IF (l_header_printed = FALSE) THEN
1490 
1491             OPI_DBI_REP_UOM_PKG.err_msg_header_spec ('VOL', 'ITEM');
1492             l_header_printed := TRUE;
1493 
1494         END IF;
1495 
1496         -- Print the missing rates.
1497         l_stmt_id := 70;
1498         OPI_DBI_REP_UOM_PKG.err_msg_missing_uoms (
1499             vol_missing_rates_rec.uom_code, s_vol_rep_uom_code);
1500 
1501         -- There is an error to report
1502         l_stmt_id := 80;
1503         l_errors := TRUE;
1504 
1505     END LOOP;
1506 
1507     -- Footer message.
1508     IF (l_header_printed = TRUE) THEN
1509         OPI_DBI_REP_UOM_PKG.err_msg_footer;
1510     END IF;
1511 
1512     return l_errors;
1513 
1514 EXCEPTION
1515 
1516     WHEN OTHERS THEN
1517         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1518                                                      l_stmt_id));
1519         RAISE ITEM_ERR_CHECK_FAILED;
1520 
1521 END check_item_setup_errors;
1522 
1523 
1524 
1525 END opi_dbi_wms_capacity_utz_pkg;