DBA Data[Home] [Help]

PACKAGE BODY: APPS.OPI_DBI_INV_CCA_PKG

Source


1 PACKAGE BODY opi_dbi_inv_cca_pkg AS
2 /*$Header: OPIDEICCAB.pls 120.9 2006/03/28 21:33:43 visgupta 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 -- DBI Global start date
17 s_global_start_date DATE;
18 s_r12_migration_date DATE;
19 
20 -- Conversion rate related variables: global currency code and rate type
21 s_global_curr_code  VARCHAR2(10);
22 s_global_rate_type  VARCHAR2(15);
23 
24 -- secondary global currency
25 s_secondary_curr_code  VARCHAR2(10);
26 s_secondary_rate_type  VARCHAR2(15);
27 
28 -- Package level variables for the user logged in
29 s_user_id    NUMBER;
30 s_login_id   NUMBER;
31 s_program_id NUMBER;
32 s_program_login_id NUMBER;
33 s_program_application_id NUMBER;
34 s_request_id NUMBER;
35 
36 /**************************************************
37 * Common Procedures (to initial and incremental load)
38 *
39 * File scope functions (not in spec)
40 **************************************************/
41 
42 -- Check for primary currency code and global start date
43 FUNCTION check_global_setup
44     RETURN BOOLEAN;
45 
46 -- Print out error message in a consistent manner
47 FUNCTION err_mesg (p_mesg IN VARCHAR2,
48                    p_proc_name IN VARCHAR2,
49                    p_stmt_id IN NUMBER)
50     RETURN VARCHAR2;
51 
52 /**************************************************
53 * Initial Load Procedures
54 *
55 * File scope functions (not in spec)
56 **************************************************/
57 
58 -- Initialization
59 PROCEDURE cca_initialize_init;
60 
61 -- Extract all MMT Cyclecount transactions into a staging table
62 PROCEDURE extract_cca_mmt_init;
63 
64 -- Extract Discrete adjustment entry data
65 PROCEDURE extract_discrete_adj_init (p_global_start_date IN DATE);
66 
67 -- Extract Process adjustment entry data
68 PROCEDURE extract_process_adj_init (p_global_start_date IN DATE);
69 
70 -- Extract the exact match entry data
71 PROCEDURE extract_exact_matches_init;
72 
73 -- Compute the conversion rates
74 PROCEDURE compute_cca_conv_rates_init (p_global_curr_code IN VARCHAR2,
75                                        p_global_rate_type IN VARCHAR2);
76 
77 -- Populate the data into the fact table
78 PROCEDURE populate_fact_init;
79 
80 
81 /**************************************************
82 * Incremental Load Procedures
83 *
84 * File scope functions (not in spec)
85 **************************************************/
86 
87 -- Initialization
88 PROCEDURE cca_initialize_incr;
89 
90 -- Extract Discrete adjustment entry data
91 PROCEDURE extract_discrete_adj_incr (p_global_start_date IN DATE);
92 
93 -- Extract Process adjustment entry data
94 PROCEDURE extract_process_adj_incr (p_global_start_date IN DATE);
95 
96 -- Extract the exact match entry data
97 PROCEDURE extract_exact_matches_incr;
98 
99 -- Compute the conversion rates
100 PROCEDURE compute_cca_conv_rates_incr (p_global_curr_code IN VARCHAR2,
101                                        p_global_rate_type IN VARCHAR2);
102 
103 -- Populate the data into the fact table
104 PROCEDURE populate_fact_incr;
105 
106 /**************************************************
107 * Common Procedures Definitions
108 **************************************************/
109 
110 /*  check_global_setup
111 
112     Checks to see if basic global parameters are set up.
113     Currently these include the:
114     1. Global start date
115     2. Global currency code
116 
117     Parameters: None
118 
119     History:
120     Date        Author              Action
121     01/12/04    Dinkar Gupta        Defined function.
122     06/07/04    Dinkar Gupta        Added initialization of all file scope
123                                     variables to this function for new
124                                     GSCC standard that does not like
125                                     initialization outside BEGIN/END block.
126 */
127 FUNCTION check_global_setup
128     RETURN BOOLEAN
129 IS
130     l_proc_name CONSTANT VARCHAR2 (40) := 'check_global_setup';
131     l_stmt_id NUMBER;
132 
133     l_setup_good BOOLEAN;
134 
135     l_list dbms_sql.varchar2_table;
136 
137 BEGIN
138 
139     -- Initialization block
140     l_setup_good := false;
141     l_stmt_id := 0;
142 
143     -- Initialize file scope static variables
144     -- Package level variables for session info-
145     -- including schema name for truncating and
146     -- collecting stats
147     s_opi_schema := NULL;
148     s_status := NULL;
149     s_industry := NULL;
150 
151     -- DBI Global start date
152     s_global_start_date := NULL;
153 
154     -- Conversion rate related variables: global currency code and rate type
155     s_global_curr_code := NULL;
156     s_global_rate_type := NULL;
157     s_secondary_curr_code := NULL;
158     s_secondary_rate_type := NULL;
159 
160     -- Package level variables for the user logged in
161     s_user_id := nvl(fnd_global.user_id, -1);
162     s_login_id := nvl(fnd_global.login_id, -1);
163     s_program_id := nvl(fnd_global.conc_program_id, -1);
164     s_program_login_id := nvl(fnd_global.conc_login_id , -1);
165     s_program_application_id := nvl(fnd_global.prog_appl_id , -1);
166     s_request_id := nvl(fnd_global.conc_request_id, -1);
167 
168     -- Parameters we want to check for
169     l_list(1) := 'BIS_PRIMARY_CURRENCY_CODE';
170     l_list(2) := 'BIS_GLOBAL_START_DATE';
171 
172     l_stmt_id := 10;
173     l_setup_good := bis_common_parameters.check_global_parameters(l_list);
174     return l_setup_good;
175 
176 EXCEPTION
177 
178     WHEN OTHERS THEN
179         rollback;
180 
181         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
182                                                      l_stmt_id));
183 
184         l_setup_good := false;
185         return l_setup_good;
186 
187 
188 END check_global_setup;
189 
190 
191 /* err_mesg
192     Return a C_ERRBUF_SIZE character long, properly formatted error
193     message with the package name, procedure name and message.
194 
195     Parameters:
196     p_mesg - Actual message to be printed
197     p_proc_name - name of procedure that should be printed in the message
198      (optional)
199     p_stmt_id - step in procedure at which error occurred
200      (optional)
201 
202     History:
203     Date        Author              Action
204     01/12/04    Dinkar Gupta        Defined function.
205 */
206 
207 FUNCTION err_mesg (p_mesg IN VARCHAR2,
208                    p_proc_name IN VARCHAR2,
209                    p_stmt_id IN NUMBER)
210     RETURN VARCHAR2
211 IS
212 
213     l_proc_name CONSTANT VARCHAR2 (60) := 'err_mesg';
214     l_stmt_id NUMBER;
215 
216     -- The variable declaration cannot take C_ERRBUF_SIZE (a defined constant)
217     -- as the size of the declaration. I have to put 300 here.
218     l_formatted_message VARCHAR2 (300);
219 
220 BEGIN
221 
222     -- initialization block
223     l_stmt_id := 0;
224 
225     -- initialization block
226     l_formatted_message := NULL;
227 
228     l_stmt_id := 10;
229     l_formatted_message := substr ((C_PKG_NAME || '.' || p_proc_name || ' #' ||
230                                    to_char (p_stmt_id) || ': ' || p_mesg),
231                                    1, C_ERRBUF_SIZE);
232 
233     commit;
234 
235     return l_formatted_message;
236 
237 EXCEPTION
238 
239     WHEN OTHERS THEN
240         -- the exception happened in the exception reporting function !!
241         -- return with ERROR.
242         l_formatted_message := substr ((C_PKG_NAME || '.' || l_proc_name ||
243                                        ' #' ||
244                                         to_char (l_stmt_id) || ': ' ||
245                                        SQLERRM),
246                                        1, C_ERRBUF_SIZE);
247 
248         l_formatted_message := 'Error in error reporting.';
249         return l_formatted_message;
250 
251 END err_mesg;
252 
253 
254 /**************************************************
255 * Initial Load Procedure Definitions
256 **************************************************/
257 
258 /* run_initial_load
259 
260     Wrapper routine for the initial load of the cycle count accuracy ETL.
261 
262     Parameters:
263     retcode - 0 on successful completion, -1 on error and 1 for warning.
264     errbuf - empty on successful completion, message on error or warning
265 
266 
267     R12 Changes
268     -----------
269     Made changes to calling of procedures and commit.
270     -------------------------------
271 
272 
273     History:
274     Date        Author              Action
275     01/12/04    Dinkar Gupta        Defined procedure.
276     03/04/04    Dinkar Gupta        Added call to OPM package.
277     07/05/05    Vishal Gupta        Made Changes for R12.
278 
279 */
280 
281 PROCEDURE run_initial_load (errbuf OUT NOCOPY VARCHAR2,
282                             retcode OUT NOCOPY NUMBER)
283 IS
284 
285     l_proc_name CONSTANT VARCHAR2 (40) := 'run_initial_load';
286     l_stmt_id NUMBER;
287 
288 
289 BEGIN
290 
291     -- initialization block
292     l_stmt_id := 0;
293 
294     l_stmt_id := 10;
295     -- Check for DBI global parameter setup, initialize file scope variables,
296     -- check for bounds and truncate tables.
297     BIS_COLLECTION_UTILITIES.PUT_LINE ('Initializing cycle count initial load ...');
298     cca_initialize_init ();
299 
300     l_stmt_id := 20;
301     -- Set up the bounds for Cycle Count accuracy in the log table.
302     -- Commit will be done
303     BIS_COLLECTION_UTILITIES.PUT_LINE (
304         'Setting up bounds for Process and Discrete ...');
305     OPI_DBI_BOUNDS_PKG.MAINTAIN_OPI_DBI_LOGS (	p_etl_type=> C_ETL_TYPE,
306 						p_load_type=> C_LOAD_INIT);
307 
308 
309     l_stmt_id := 30;
310     -- Make a call to the OPM extraction for PreR12. Do this within
311     -- a begin/end block and throw a custom exception if the
312     -- OPM code ends with an error.
313     -- first check R12 migration date > GSD
314     BIS_COLLECTION_UTILITIES.PUT_LINE ('R12 Migration Date ...' || s_r12_migration_date);
315 
316     -- R12 date will not be null. There will be some suitable date returned by
317     -- opi_dbi_rpt_util_pkg.get_inv_convergence_date
318     IF (s_r12_migration_date > s_global_start_date) THEN
319     --{
320         BIS_COLLECTION_UTILITIES.PUT_LINE (
321                 'Extracting data for Pre R12 rocess manufacturing organizations ....');
322         BEGIN
323 
324                 opi_dbi_inv_cca_opm_pkg.run_initial_load_opm (errbuf, retcode);
325                 commit;  -- commit if successful
326 
327 
328         EXCEPTION
329 
330                 WHEN OTHERS THEN
331                 RAISE OPM_EXTRACTION_ERROR;
332 
333         END;
334     --}
335     ELSE
336     --{
337         BIS_COLLECTION_UTILITIES.PUT_LINE (
338         'Migration date is less than GSD. Skipping PreR12 Process Cycle Count Extraction ....');
339     --}
340     END IF;
341 
342 
343     l_stmt_id := 40;
344     -- Extract all Cycle count transactions from MMT inot a staging table
345     BIS_COLLECTION_UTILITIES.PUT_LINE (
346         'Extracting cycle count trasnactions into a staging table ...');
347     extract_cca_mmt_init ();
348 
349     l_stmt_id := 50;
350     --
351     commit;
352 
353     l_stmt_id := 55;
354     -- Call API to load ledger data into Global temp table
355     -- This temp table will be joined to extract process adjustments
356     BIS_COLLECTION_UTILITIES.PUT_LINE (
357         'Loading Ledger data into temp table ...');
358     OPI_DBI_BOUNDS_PKG.load_opm_org_ledger_data;
359 
360      l_stmt_id := 57;
361     -- Committing the data. Since the temp table is made with On Commit preserve rows
362     -- there will be no problem.
363     commit;
364 
365     l_stmt_id := 60;
366     -- Extract the adjustment entry data from MMT/MTA using the
367     -- bounds just set up.
368     BIS_COLLECTION_UTILITIES.PUT_LINE (
369         'Extracting cycle count adjustment information for discrete manufacturing orgs ...');
370     extract_discrete_adj_init (s_global_start_date);
371 
372      l_stmt_id := 70;
373     -- Due to the bulk insert in parallel mode, commit before
374     -- inputting more data to the staging table.
375     commit;
376 
377     l_stmt_id := 80;
378     -- Extract the adjustment entry data from MMT/MTA using the
379     -- bounds just set up.
380     BIS_COLLECTION_UTILITIES.PUT_LINE (
381         'Extracting cycle count adjustment information for Process manufacturing orgs ...');
382     extract_process_adj_init (s_global_start_date);
383 
384     l_stmt_id := 90;
385     -- Due to the bulk insert in parallel mode, commit before
386     -- inputting more data to the staging table.
387     commit;
388 
389     l_stmt_id := 100;
390     -- Extract the exact matches entry data from MCCE. Collect all rows
391     -- with last_update_date greater than the global start date.
392     BIS_COLLECTION_UTILITIES.PUT_LINE (
393         'Extracting cycle count exact match information for discrete manufacturing organizations ...');
394     extract_exact_matches_init ();
395 
396     l_stmt_id := 110;
397     -- Due to the bulk insert in parallel mode, commit before
398     -- moving ahead.
399     commit;
400 
401     l_stmt_id := 120;
402     -- Compute the conversion rates for all org/date pairs in the
403     -- staging table. This API will now commit, due to an
404     -- insert+append hint.
405     BIS_COLLECTION_UTILITIES.PUT_LINE (
406         'Computing conversion rates for all extracted cycle counting data ...');
407     compute_cca_conv_rates_init (s_global_curr_code, s_global_rate_type);
408 
409     l_stmt_id := 130;
410     -- Commit the conversion rates found before finally merging all
411     -- data to the fact table.
412     commit;
413 
414     l_stmt_id := 140;
415     -- Insert all the data into the fact table in one shot.
416     BIS_COLLECTION_UTILITIES.PUT_LINE ('Inserting data into the fact table ...');
417     populate_fact_init ();
418 
419     l_stmt_id := 150;
420     -- Update the bounds table
421     BIS_COLLECTION_UTILITIES.PUT_LINE ('Updating run time bounds for next run ...');
422     OPI_DBI_BOUNDS_PKG.SET_LOAD_SUCCESSFUL(C_ETL_TYPE, C_LOAD_INIT);
423 
424     l_stmt_id := 160;
425     -- Truncate the staging table, commit the data to the fact table
426     -- and update the CCA related bounds in one database transaction
427     -- for consistency.
428     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
429                        'opi_dbi_inv_cca_stg');
430 
431     l_stmt_id := 170;
432     -- Truncate the MMT staging table, commit the data to the fact table
433     -- and update the CCA related bounds in one database transaction
434     -- for consistency.
435     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
436                        'opi_dbi_mmt_cca_stg');
437 
438 
439     -- return successfully
440     retcode := C_SUCCESS;
441     errbuf := '';
442 
443     BIS_COLLECTION_UTILITIES.PUT_LINE ('Cycle count data extracted into the fact table successfully.');
444 
445     RETURN;
446 
447 EXCEPTION
448 
449 
450     WHEN INITIALIZATION_ERROR THEN
451 
452         rollback;
453 
454         -- report the error
455         retcode := C_ERROR;
456         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
457         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
458                                             (INITIALIZATION_ERROR_MESG,
459                                              l_proc_name, l_stmt_id));
460         RETURN;
461 
462     WHEN BOUNDS_SETUP_ERROR THEN
463 
464         rollback;
465 
466         -- report the error
467         retcode := C_ERROR;
468         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
469         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
470                                             (BOUNDS_SETUP_ERROR_MESG,
471                                              l_proc_name, l_stmt_id));
472         RETURN;
473 
474 
475     WHEN ADJUSTMENT_EXTR_ERROR THEN
476 
477         rollback;
478 
479         -- report the error
480         retcode := C_ERROR;
481         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
482         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
483                                             (ADJUSTMENT_EXTR_ERROR_MESG,
484                                              l_proc_name, l_stmt_id));
485         RETURN;
486 
487 
488     WHEN EXACT_MATCH_EXTR_ERROR THEN
489 
490         rollback;
491 
492         -- report the error
493         retcode := C_ERROR;
494         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
495         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
496                                             (EXACT_MATCH_EXTR_ERROR_MESG,
497                                              l_proc_name, l_stmt_id));
498         RETURN;
499 
500     WHEN BOUNDS_UPDATE_ERROR THEN
501 
502         rollback;
503 
504         -- report the error
505         retcode := C_ERROR;
506         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
507         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
508                                             (BOUNDS_UPDATE_ERROR_MESG,
509                                              l_proc_name, l_stmt_id));
510         RETURN;
511 
512 
513     WHEN CONV_RATES_ERROR THEN
514 
515         rollback;
516 
517         -- report the error
518         retcode := C_ERROR;
519         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
520         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
521                                             (CONV_RATES_ERROR_MESG,
522                                              l_proc_name, l_stmt_id));
523         RETURN;
524 
525 
526     WHEN FACT_MERGE_ERROR THEN
527 
528         rollback;
529 
530         -- report the error
531         retcode := C_ERROR;
532         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
533         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
534                                             (FACT_MERGE_ERROR_MESG,
535                                              l_proc_name, l_stmt_id));
536         RETURN;
537 
538 
539     WHEN OPM_EXTRACTION_ERROR THEN
540 
541         rollback;
542 
543         -- report the error
544         retcode := C_ERROR;
545         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
546         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
547                                             (OPM_EXTRACTION_ERROR_MESG,
548                                              l_proc_name, l_stmt_id));
549         RETURN;
550 
551     WHEN OTHERS THEN
552 
553         rollback;
554 
555         -- report the error
556         retcode := C_ERROR;
557         errbuf := 'Inventory Cycle Count Accuracy ETL initial load terminated with errors. Please check the concurrent program log file for errors.';
558 
559         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
560                                                      l_stmt_id));
561 
562         RETURN;
563 
564 
565 END run_initial_load;
566 
567 
568 /* cca_initialize_init
569 
570     Check that the primary currency code and global start date have been
571     set up.
572 
573     Get the OPI schema info.
574 
575     Check if the log table has rows created by the Inventory Value ETL.
576 
577     Truncate all the needed tables for the initial load.
578 
579     Note: Do not check to see if this initial load has been run previously.
580 
581     History:
582     Date        Author              Action
583     01/12/04    Dinkar Gupta        Defined procedure.
584     04/13/04    Dinkar Gupta        Changed procedure so that it does not
585                                     throw an exception in case no MMT/MIF
586                                     rows are found in the log. The behaviour
587                                     can happen in case of purely process
588                                     manufacturing instances.
589     05/14/04    Dinkar Gupta        Added hints to alter SQL hash and sort
590                                     area sizes based on perf team
591                                     recommendation.
592     08/17/04    Dinkar Gupta        Added Secondary Currency support.
593 
594     07/05/05    Vishal Gupta        Made changes for R12. No check
595                                     pertaining to logs
596 */
597 
598 PROCEDURE cca_initialize_init
599 IS
600 
601     l_proc_name CONSTANT VARCHAR2 (40) := 'cca_initialize_init';
602     l_stmt_id NUMBER;
603 
604 
605 BEGIN
606 
607     -- initialization block
608     l_stmt_id := 0;
609 
610     l_stmt_id := 10;
611     -- Check for the primary currency code and global start date setup.
612     -- These two parameters must be set up prior to any DBI load.
613     IF (NOT (check_global_setup ())) THEN
614         RAISE GLOBAL_SETUP_MISSING;
615     END IF;
616 
617     l_stmt_id := 20;
618     -- Obtain the OPI schema name to allow truncation of various tables
619     -- get session parameters
620     IF (NOT (fnd_installation.get_app_info('OPI', s_status, s_industry,
621                                            s_opi_schema))) THEN
622         RAISE SCHEMA_INFO_NOT_FOUND;
623     END IF;
624 
625 
626     -- Get the global start date
627     l_stmt_id := 30;
628     s_global_start_date := trunc (bis_common_parameters.get_global_start_date);
629     IF (s_global_start_date IS NULL) THEN
630         RAISE GLOBAL_START_DATE_NULL;
631     END IF;
632 
633 
634     l_stmt_id := 40;
635     -- Get the DBI global currency code
636     s_global_curr_code := bis_common_parameters.get_currency_code;
637 
638     l_stmt_id := 50;
639     IF (s_global_curr_code IS NULL) THEN
640         RAISE NO_GLOBAL_CURR_CODE;
641     END IF;
642 
643 
644     l_stmt_id := 60;
645     -- Get the DBI Global rate type
646     s_global_rate_type := bis_common_parameters.get_rate_type;
647 
648     l_stmt_id := 70;
649     IF (s_global_rate_type IS NULL) THEN
650         RAISE NO_GLOBAL_RATE_TYPE;
651     END IF;
652 
653     l_stmt_id := 80;
654     -- Get the DBI secondary currency code
655     s_secondary_curr_code := bis_common_parameters.get_secondary_currency_code;
656 
657     l_stmt_id := 90;
658     -- Get the DBI Global rate type
659     s_secondary_rate_type := bis_common_parameters.get_secondary_rate_type;
660 
661     l_stmt_id := 100;
662     IF (    (s_secondary_curr_code IS NULL AND
663              s_secondary_rate_type IS NOT NULL)
664          OR (s_secondary_curr_code IS NOT NULL AND
665              s_secondary_rate_type IS NULL) ) THEN
666         RAISE SEC_CURR_SETUP_INVALID;
667     END IF;
668 
669 
670     -- Truncate the following tables (in case of exceptions, nothing
671     -- special to do here because it is a database error):
672 
673     l_stmt_id := 120;
674     -- Staging table
675     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
676                        'opi_dbi_inv_cca_stg');
677 
678     l_stmt_id := 130;
679     -- Staging table
680     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
681                        'opi_dbi_mmt_cca_stg');
682 
683     l_stmt_id := 140;
684     -- Conversion rates table
685     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
686                        'opi_dbi_inv_cca_conv');
687 
688 
689     l_stmt_id := 150;
690     -- MV Log on the fact table, because the purge directive on the
691     -- fact table does not work.
692     --EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
693     --                 'mlog$_opi_dbi_inv_cca_f' );
694 
695 
696     l_stmt_id := 160;
697     -- Fact table including the MV log on the table, for efficiency
698     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
699                        'opi_dbi_inv_cca_f PURGE MATERIALIZED VIEW LOG');
700 
701 
702     -- Not using
703     l_stmt_id := 170;
704     -- Temp table for bounds computation
705     -- EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
706        --                'opi_dbi_inv_value_log_tmp');
707 
708 
709     l_stmt_id := 180;
710     -- User and login id's
711     s_user_id := nvl(fnd_global.user_id, -1);
712     s_login_id := nvl(fnd_global.login_id, -1);
713     s_program_id := nvl(fnd_global.conc_program_id, -1);
714     s_program_login_id := nvl(fnd_global.conc_login_id , -1);
715     s_program_application_id := nvl(fnd_global.prog_appl_id , -1);
716     s_request_id := nvl(fnd_global.conc_request_id, -1);
717 
718     l_stmt_id := 190;
719     -- Initial load requires lots of memory for OLTP table
720     -- hash joins. Performance team recommends the following
721     -- 2 alter session commands.
722     EXECUTE IMMEDIATE ('ALTER SESSION SET SORT_AREA_SIZE=100000000');
723     EXECUTE IMMEDIATE ('ALTER SESSION SET HASH_AREA_SIZE=100000000');
724 
725     l_stmt_id := 200;
726     -- R12 Migration date
727     -- will be uncommented when this package is available
728     opi_dbi_rpt_util_pkg.get_inv_convergence_date (s_r12_migration_date);
729 
730     RETURN;
731 
732 EXCEPTION
733 
734     WHEN GLOBAL_SETUP_MISSING THEN
735 
736         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (GLOBAL_SETUP_MISSING_MESG,
737                                                      l_proc_name, l_stmt_id));
738         RAISE INITIALIZATION_ERROR;
739 
740     WHEN SCHEMA_INFO_NOT_FOUND THEN
741 
742         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
743                                             (SCHEMA_INFO_NOT_FOUND_MESG,
744                                              l_proc_name, l_stmt_id));
745         RAISE INITIALIZATION_ERROR;
746 
747     WHEN INIT_BOUNDS_MISSING THEN
748 
749         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
750                                             (INIT_BOUNDS_MISSING_MESG,
751                                              l_proc_name, l_stmt_id));
752         RAISE INITIALIZATION_ERROR;
753 
754     WHEN GLOBAL_START_DATE_NULL THEN
755 
756         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
757                                             (GLOBAL_START_DATE_NULL_MESG,
758                                              l_proc_name, l_stmt_id));
759         RAISE INITIALIZATION_ERROR;
760 
761 
762     WHEN NO_GLOBAL_CURR_CODE THEN
763 
764         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
765                                             (NO_GLOBAL_CURR_CODE_MESG,
766                                              l_proc_name, l_stmt_id));
767         RAISE INITIALIZATION_ERROR;
768 
769 
770     WHEN NO_GLOBAL_RATE_TYPE THEN
771 
772         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
773                                             (NO_GLOBAL_RATE_TYPE_MESG,
774                                              l_proc_name, l_stmt_id));
775         RAISE INITIALIZATION_ERROR;
776 
777 
778     WHEN SEC_CURR_SETUP_INVALID THEN
779         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
780                                             (SEC_CURR_SETUP_INVALID_MESG,
781                                              l_proc_name, l_stmt_id));
782 
783         RAISE INITIALIZATION_ERROR;
784 
785     WHEN OTHERS THEN
786 
787         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
788                                                      l_stmt_id));
789 
790         RAISE INITIALIZATION_ERROR;
791 
792 
793 END cca_initialize_init;
794 
795 /* extract_cca_mmt_init
796 
797    Extract Cycle count type of transactions from MMT which are after Global
798    start date. For this transaction_source_type_id = 9 . This contains 2
799    type of Cycle count transactions :
800    Transaction_type_id = 4  Cycle Count Adjustments
801    Trasnaction_type_id = 5  Cycle Count Subinventory Transfer
802 
803 */
804 
805 PROCEDURE extract_cca_mmt_init
806 IS
807         l_stmt_id       NUMBER;
808         l_proc_name     VARCHAR2(40) := 'Extract_cca_mmt_init';
809 
810 BEGIN
811 
812     l_stmt_id :=0 ;
813 
814 
815     Insert /*+ append parallel (opi_dbi_mmt_cca_stg) */
816     into OPI_DBI_MMT_CCA_STG
817             (TRANSACTION_ID,
818             ORGANIZATION_ID,
819             INVENTORY_ITEM_ID,
820             CYCLE_COUNT_ID,
821             SUBINVENTORY_CODE,
822             TRANSFER_SUBINVENTORY,
823             TRANSACTION_DATE,
824             TRANSACTION_TYPE_ID,
825             PRIMARY_QUANTITY)
826     Select TRANSACTION_ID,
827             ORGANIZATION_ID,
828             INVENTORY_ITEM_ID,
829             CYCLE_COUNT_ID,
830             SUBINVENTORY_CODE,
831             TRANSFER_SUBINVENTORY,
832             TRANSACTION_DATE,
833             TRANSACTION_TYPE_ID,
834             PRIMARY_QUANTITY
835     From   MTL_MATERIAL_TRANSACTIONS
836     Where Transaction_date >= s_global_start_date
837     and   Transaction_source_type_id = 9 ;
838 
839 
840     -- commit will handled in wrapper
841 
842 
843     RETURN;
844 
845 EXCEPTION
846 
847     WHEN OTHERS THEN
848 
849         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
850                                                      l_stmt_id));
851 
852         RAISE CCA_MMT_STG_ERROR;
853 
854 END extract_cca_mmt_init;
855 
856 
857 /* extract_discrete_adj_init
858 
859     Extract discrete adjustment entry data from MTL_CYCLE_COUNT_ENTRIES (MCCE),
860     MMT and MTA. Adjustments can get costed well after approval and
861     interim cost updates may cause the values recorded in MCCE to
862     be different. Thus we need to get the cost associated to the item
863     using the value in MTA so that the reported adjustments match
864     the MTA reported value.
865 
866     However, due to issues with layered costing in LIFO/FIFO orgs, the
867     system inventory value is computed using the cost at the time when
868     the entry was made. Thus the reported system inventory value
869     matches the one reported in Oracle Forms.
870 
871     We are only interested in entries completed after the global start
872     date (i.e. entry_status_code = 5 and approval_date > global start date).
873     But it is not possible mmt_mta join to return records where cycle count
874     entries are not completed.
875 
876     The only MTA rows we are interested in are those that affect the
877     inventory account (accounting line type = 1).
878 
879     MTA does not store rows for expense items, or items in expense
880     subinventories. Thus the join between MMT and MTA will have to
881     be an outer join. Rows with no matches will be assigned an
882     item cost of 0.
883 
884     MCCE does not store quantities in the primary uom_code. If the
885     transaction uom is not the same as the primary uom, all
886     quantities will have to be converted to the primary uom.
887 
888     There is a need to check for adjustment quantity = 0 serial item counts
889     can have count level matches, but serial number level adjustments,
890     To handle this, make four enhancements:
891     1. Declare exact matches if the sum of the MMT primary quantity is 0.
892     2. Pick the MCCE item_unit_cost if the quantity is 0 (check for expense
893        subs before that).
894     3. Set the tolerance to 0 if there is an adjustment in another
895        subinventory that the one counted. This will automatically
896        make any adjustments against it misses.
897     4. The system_inventory_qty for the other subinventory is the negative
898        of the adjustment quantity, so that the sum of the adjustment
899        and system quantity is always 0.
900 
901     We will only be scanning MMT rows between the transaction ranges
902     in the log table.
903 
904     Also, since the fact table is at a cycle count entry level,
905     it is impossible for the sum (mmt.primary_quantity) to be 0. Thus
906     the item_cost formula of sum (value)/sum (quantity) is always
907     valid and we need not worry about sum (quantity) being 0 or NULL.
908 
909     Since the join conditions between MCCE - MMT - MTA is one to many
910     to many, join MMT/MTA on transaction_id first.
911 
912     Also, to handle serial item adjustments where the adjustment
913     automatically issues an item from a sub to move it to the next,
914     use the subinventory_code from MMT, not MCCE.
915 
916     There cannot be an entry in MMT and MTA for which cycle count has not been approved.
917     ie entry_status_code = 5.
918 
919     -------- R12 Changes
920     1> Subinventory Transfer type of transaction (MMT.transaction_type_id = 5)
921        is seen in Cycle Count. This case occurs when a LPN is received in
922        say subinv. BULK, and cycle count is done in say subinv. CASE for a specific LPN.
923        This type of transaction has 2 rows in MMT, one for issue transaction
924        and other for receipt transaction. But the MTA has no rows for receipt
925        transaction while it has 2 entries differing only in MTA.primary_quantity.
926 
927        The subinventory for issue transaction where mta.primary_quantity is -ve and
928        transfer_subinventory for issue transaction where mta.primary_quantity is
929        positive.
930        This case will not be encountered for Expense item as LPN cannot be made
931        for expense item.
932        Such transactions can only be done through Warehouse mobile.
933 
934 
935        Currently for such transactions MMT.cycle_count_id is not populated.
936        Bug # 4392340 has been logged for the same.
937 
938     2> Changes to log table and columns.
939 
940     3> mmt staging table is introduced to collect all mmt transactions
941        for discrete and process orgs at one go. Here as we are joining
942        with bounds table which has bounds for discrete orgs by
943        transaction_id we do not need to put any filters to get only
944        discrete organizations. For process there is one single record in
945        bounds table which has bound_level_entity_id as NULL and hence mmt
946        records for process orgs will not be selected in the extract
947        below.
948 
949 
950     ----------------------
951 
952 
953     Do not commit data. Let the wrapper coordinate committing of data.
954 
955     Paramters:
956     IN:
957         p_global_start_date - DBI global start date
958 
959     History:
960     Date        Author              Action
961     01/14/04    Dinkar Gupta        Defined procedure.
962     02/10/04    Dinkar Gupta        Added group by transaction_id
963                                     in the mmt/mta join.
964                                     Used MMT subinventory_code
965                                     to handle serial item issues.
966     02/18/04    Dinkar Gupta        Added condition to handle
967                                     cases where MMT quantity is 0 for
968                                     serial items.
969                                     Also added condition to report miss
970                                     for adjustments against any other
971                                     sub than the one being counted.
972     03/10/04    Dinkar Gupta        Used item_cost from MCCE for system
973                                     inventory value for LIFO/FIFO org
974                                     issue.
975     06/22/05    Vishal Gupta        Refer to R12 Changes in the above
976                                     header.
977 
978 
979 */
980 PROCEDURE extract_discrete_adj_init (p_global_start_date IN DATE)
981 IS
982     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_adjustments_init';
983     l_stmt_id           NUMBER;
984 
985 BEGIN
986 
987     -- initialization block
988     l_stmt_id := 0;
989 
990     l_stmt_id := 10;
991     -- This procedure only inserts all adjustment entry data into the
992     -- staging table. For an explanation of the logic, please refer to the
993     -- procedure header.
994 
995     -- Join condition justifications
996     --
997     -- to MCCC - on org, header and abc_class. The org is redundant,
998     -- but this should allow use of U1 index on MCCC.
999     --
1000     -- to MCCI - on header and item. This should allow use of U1 index
1001     -- on MCCI.
1002     --
1003     -- to MCCH - on header. This should allow use of U1 index.
1004     --
1005     -- to MCCE - on entry. This should allow use of U1 index.
1006     --
1007     -- to MSI - on org and item. This should allow use of the U1 index.
1008     --
1009     -- to SUBS - on org and subinventory code
1010     INSERT /*+ append parallel (opi_dbi_inv_cca_stg) */
1011     INTO opi_dbi_inv_cca_stg (
1012         organization_id,
1013         inventory_item_id,
1014         cycle_count_header_id,
1015         abc_class_id,
1016         subinventory_code,
1017         cycle_count_entry_id,
1018         source,
1019         approval_date,
1020         uom_code,
1021         system_inventory_qty,
1022         positive_adjustment_qty,
1023         negative_adjustment_qty,
1024         item_unit_cost,
1025         item_adj_unit_cost,
1026         hit_miss_pos,
1027         hit_miss_neg,
1028         exact_match)
1029     SELECT /*+ parallel(mcce) parallel(mcch) parallel(mcci)
1030                parallel(mccc) parallel(msi) parallel(subs)
1031                parallel(mmt_mta)
1032                use_hash(mcce mcch mcci mccc msi subs) */
1033         mcce.organization_id,
1034         mcce.inventory_item_id,
1035         mcce.cycle_count_header_id,
1036         to_char (mccc.abc_class_id),
1037         mmt_mta.subinventory_code,
1038         to_char (mcce.cycle_count_entry_id),
1039         C_OPI_SOURCE,
1040         trunc (mcce.approval_date),
1041         msi.primary_uom_code,
1042         decode (mcce.count_uom_current,
1043                 msi.primary_uom_code,
1044                 decode (mmt_mta.subinventory_code,
1045                         mcce.subinventory, mcce.system_quantity_current,
1046                         -1 * sum (mmt_mta.primary_quantity)),
1047                 decode (mmt_mta.subinventory_code,
1048                         mcce.subinventory,
1049                         inv_convert.inv_um_convert
1050                             (mcce.inventory_item_id, C_MMT_PRECISION,
1051                              mcce.system_quantity_current,
1052                              mcce.count_uom_current,
1053                              msi.primary_uom_code, NULL, NULL),
1054                         inv_convert.inv_um_convert
1055                             (mcce.inventory_item_id, C_MMT_PRECISION,
1056                              -1 * sum (mmt_mta.primary_quantity),
1057                              mcce.count_uom_current,
1058                              msi.primary_uom_code, NULL, NULL))),
1059         CASE WHEN sum (mmt_mta.primary_quantity) > 0 THEN
1060                     sum (mmt_mta.primary_quantity)
1061              ELSE   0
1062              END,
1063         CASE WHEN sum (mmt_mta.primary_quantity) < 0 THEN
1064                     -1 * sum (mmt_mta.primary_quantity)
1065              ELSE   0
1066              END,
1067         decode (subs.asset_inventory,
1068                 C_EXPENSE_SUBINVENTORY, 0,
1069                 mcce.item_unit_cost),
1070         decode (sum (mmt_mta.primary_quantity),
1071                 0, decode (subs.asset_inventory,
1072                            C_EXPENSE_SUBINVENTORY, 0,
1073                            mcce.item_unit_cost),
1074                 nvl (sum (mmt_mta.base_transaction_value)/
1075                      sum (mmt_mta.primary_quantity), 0)),
1076         decode (mmt_mta.subinventory_code,
1077                 mcce.subinventory, nvl (mccc.hit_miss_tolerance_positive,
1078                                         mcch.hit_miss_tolerance_positive),
1079                 0),
1080         decode (mmt_mta.subinventory_code,
1081                 mcce.subinventory, nvl (mccc.hit_miss_tolerance_negative,
1082                                         mcch.hit_miss_tolerance_negative),
1083                 0),
1084         decode (sum (mmt_mta.primary_quantity),
1085                 0, C_EXACT_MATCH,
1086                 C_NO_MATCH)
1087       FROM  mtl_cycle_count_entries mcce,
1088             mtl_cycle_count_headers mcch,
1089             mtl_cycle_count_items mcci,
1090             mtl_cycle_count_classes mccc,
1091             mtl_system_items_b msi,
1092             mtl_secondary_inventories subs,
1093             (SELECT /*+ no_merge
1094                         parallel(mmt) parallel(mta) parallel(log)
1095                         use_hash(mmt mta log)*/
1096                 mmt.organization_id,
1097                 mmt.inventory_item_id,
1098                 mmt.transaction_date,
1099                 mmt.cycle_count_id,
1100                 decode (mmt.transaction_type_id,
1101                         5, decode(sign(nvl(mta.primary_quantity,0)),
1102                                   1, 0,
1103                                   mmt.primary_quantity),
1104                         mmt.primary_quantity)   primary_quantity,
1105                 decode (mmt.transaction_type_id,
1106                         5, decode(sign(nvl(mta.primary_quantity,0)),
1107                                   1, mmt.transfer_subinventory,
1108                                   mmt.subinventory_code),
1109                         mmt.subinventory_code)  subinventory_code,
1110                 sum (mta.base_transaction_value) base_transaction_value
1111               FROM opi_dbi_mmt_cca_stg mmt,
1112                    mtl_transaction_accounts mta,
1113                    opi_dbi_conc_prog_run_log log
1114               WHERE log.etl_type = C_ETL_TYPE
1115                 AND log.driving_table_code = C_LOG_MMT_DRV_TBL
1116                 AND log.load_type = C_LOAD_INIT
1117                 AND mmt.organization_id = log.bound_level_entity_id
1118                 AND mmt.transaction_id >= log.from_bound_id
1119                 AND mmt.transaction_id <  log.to_bound_id
1120                 AND mmt.transaction_date >= p_global_start_date
1121          --     AND mmt.transaction_type_id = C_MMT_CYCLE_COUNT_ADJ
1122                 AND mmt.transaction_id = mta.transaction_id (+)
1123                 AND nvl (mta.accounting_line_type, C_INVENTORY_ACCOUNT) =
1124                         C_INVENTORY_ACCOUNT -- 1
1125               GROUP BY
1126                     mmt.organization_id,
1127                     mmt.inventory_item_id,
1128                     mmt.transaction_date,
1129                     mmt.cycle_count_id,
1130                     decode (mmt.transaction_type_id,
1131                         5, decode(sign(nvl(mta.primary_quantity,0)),
1132                                   1, 0,
1133                                   mmt.primary_quantity),
1134                         mmt.primary_quantity),
1135                     decode (mmt.transaction_type_id,
1136                         5, decode(sign(nvl(mta.primary_quantity,0)),
1137                                   1, mmt.transfer_subinventory,
1138                                   mmt.subinventory_code),
1139                         mmt.subinventory_code),
1140                     mmt.transaction_id) mmt_mta
1141       WHERE mmt_mta.organization_id = msi.organization_id
1142         AND mmt_mta.inventory_item_id = msi.inventory_item_id
1143         AND mmt_mta.cycle_count_id = mcce.cycle_count_entry_id
1144         AND mcce.entry_status_code = C_COMPLETED_CCA_ENTRY
1145         AND mcce.cycle_count_header_id = mcch.cycle_count_header_id
1146         AND mcce.cycle_count_header_id = mcci.cycle_count_header_id
1147         AND mcce.inventory_item_id = mcci.inventory_item_id
1148         AND mcce.organization_id = mccc.organization_id
1149         AND mcce.cycle_count_header_id = mccc.cycle_count_header_id
1150         AND mcci.abc_class_id = mccc.abc_class_id
1151         AND mmt_mta.organization_id = subs.organization_id
1152         AND mmt_mta.subinventory_code = subs.secondary_inventory_name
1153       GROUP BY
1154         mcce.organization_id,
1155         mcce.inventory_item_id,
1156         mcce.cycle_count_header_id,
1157         mccc.abc_class_id,
1158         mmt_mta.subinventory_code,
1159         mcce.cycle_count_entry_id,
1160         trunc (mcce.approval_date),
1161         msi.primary_uom_code,
1162         mcce.count_uom_current,
1163         mcce.system_quantity_current,
1164         subs.asset_inventory,
1165         mcce.item_unit_cost,
1166         mcce.subinventory,
1167         mccc.hit_miss_tolerance_positive,
1168         mcch.hit_miss_tolerance_positive,
1169         mcce.subinventory,
1170         mccc.hit_miss_tolerance_negative,
1171         mcch.hit_miss_tolerance_negative;
1172 
1173     RETURN;
1174 
1175 EXCEPTION
1176 
1177     WHEN OTHERS THEN
1178 
1179         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1180                                                      l_stmt_id));
1181 
1182         RAISE ADJUSTMENT_EXTR_ERROR;
1183 
1184 END extract_discrete_adj_init;
1185 
1186 
1187 
1188 /* extract_process_adj_init
1189    Extract process adjustment entry data from MTL_CYCLE_COUNT_ENTRIES (MCCE),
1190     MMT and GTV. The transactions in GTV can be either in Draft, New or Final Mode.
1191     We will only consider Draft and Final Mode of transactions only.
1192 
1193     For initial load there will not be any separate bounds for Final and Draft
1194     transaction.
1195 
1196     Subinventory Transafer type of transaction for Cycle Count is considered. There
1197     is no change from discrete.
1198 
1199         1> Subinventory Transfer type of transaction (MMT.transaction_type_id = 5)
1200        is seen in Cycle Count. This case occurs when a LPN is received in
1201        say BULK, and cycle count is done in say CASE for a specific LPN.
1202        This type of transaction has 2 rows in MMT, one for issue transaction
1203        and other for receipt transaction. But the GTV has no rows for receipt
1204        transaction while it has 2 entries differing only in GTV.subinventory_code.
1205        GTV.subinventory_code will have issue subinventory_code for one of two rows in GTV
1206        pertianing to issue transaction in MMT. The other row will have
1207        MMT.transfer_subinventory in GTV.subinventory_code.
1208 
1209 
1210        Currently for such transactions MMT.cycle_count_id is not populated.
1211        Bug # 4392340 has been logged for the same.
1212 
1213     The bounds for Process is applied same for all organization. The driving table
1214     will be GTV.
1215     To isolate cycle count transaction in GTV following is required:
1216     EVENT_CLASS_CODE = 'MISC_TXN' and 'SUBINV_XFER'
1217     EVENT_TYPE_CODE = 'CYCLE_COUNT_ADJ'	 and 'CYCLE_COUNT_XFER'
1218     JOURNAL_LINE_TYPE = 'INV'
1219     TRANSACTION_SOURCE = 'INVENTORY'
1220 
1221     We are only interested in entries completed after the global start
1222     date (i.e. entry_status_code = 5 and approval_date > global start date).
1223 
1224     Unlike the case with MTA, GTV has rows for expense items, or items in
1225     expense subinventories. Hence also no outer join is required.
1226 
1227     For item_unit_cost, adjustments can get costed well after approval and interim
1228     cost updates may cause the values recorded in MCCE to be different. Thus
1229     we need to get the cost associated to the item using the value in GTV so
1230     that the reported adjustments match the GTV reported value.
1231 
1232     However, due to issues with layered costing in LIFO/FIFO orgs, the
1233     system inventory value is computed using the cost at the time when
1234     the entry was made. Thus the reported system inventory value
1235     matches the one reported in Oracle Forms.
1236 
1237     MCCE does not store quantities in the primary uom_code. If the
1238     transaction uom is not the same as the primary uom, all
1239     quantities will have to be converted to the primary uom.
1240 
1241     Also, since the fact table is at a cycle count entry level,
1242     it is impossible for the sum (mmt.primary_quantity) to be 0. Thus
1243     the item_cost formula of sum (value)/sum (quantity) is always
1244     valid and we need not worry about sum (quantity) being 0 or NULL.
1245 
1246     Since the join conditions between MCCE - MMT - GTV is one to many
1247     to many, join GTV/MMT on transaction_id first.
1248 
1249     IMPORTANT NOTE R12:
1250     -------------------
1251     draft and permanent quantity/value is not handled separately as in
1252     other ETLs as its assumed that either all the MMT-GTV records are
1253     in draft or permanent status for one cycle count entries.
1254 
1255     Now, as we relook at all the draft records in every ETL its
1256     possible that same draft records are collected again. But as our
1257     fact is at cycle_count_entry level its assumed that either all or
1258     none of MMT-GTV for a cycle count entry are collected. Hence in
1259     Merge of cycle count values are only replaced and not added.
1260 
1261     Do not commit data. Let the wrapper coordinate committing of data.
1262 
1263     Paramters:
1264     IN:
1265         p_global_start_date - DBI global start date
1266 
1267     History:
1268     Date        Author              Action
1269     06/22/05    Vishal Gupta        New Procedure. To collect data for
1270                                     Post R12 Process cycle counting,
1271 
1272 
1273 */
1274 PROCEDURE extract_process_adj_init (p_global_start_date IN DATE)
1275 IS
1276     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_adjustments_init';
1277     l_stmt_id           NUMBER;
1278 
1279     l_from_bound_date   OPI_DBI_CONC_PROG_RUN_LOG.from_bound_date%type;
1280     l_to_bound_date     OPI_DBI_CONC_PROG_RUN_LOG.to_bound_date%type;
1281 
1282 BEGIN
1283 
1284     -- initialization block
1285     l_stmt_id := 0;
1286 
1287     SELECT from_bound_date, to_bound_date
1288     INTO l_from_bound_date, l_to_bound_date
1289     FROM OPI_DBI_CONC_PROG_RUN_LOG
1290     WHERE driving_table_code = C_LOG_GTV_DRV_TBL
1291       AND etl_type = C_ETL_TYPE
1292       AND load_type = C_LOAD_INIT;
1293 
1294 
1295     l_stmt_id := 10;
1296     -- This procedure only inserts all adjustment entry data into the
1297     -- staging table. For an explanation of the logic, please refer to the
1298     -- procedure header.
1299 
1300     -- Join condition justifications
1301     --
1302     -- to MCCC - on org, header and abc_class. The org is redundant,
1303     -- but this should allow use of U1 index on MCCC.
1304     --
1305     -- to MCCI - on header and item. This should allow use of U1 index
1306     -- on MCCI.
1307     --
1308     -- to MCCH - on header. This should allow use of U1 index.
1309     --
1310     -- to MCCE - on entry. This should allow use of U1 index.
1311     --
1312     -- to MSI - on org and item. This should allow use of the U1 index.
1313     --
1314     -- to SUBS - on org and subinventory code
1315 
1316 
1317      INSERT /*+ append parallel (opi_dbi_inv_cca_stg) */
1318      INTO opi_dbi_inv_cca_stg (
1319         organization_id,
1320         inventory_item_id,
1321         cycle_count_header_id,
1322         abc_class_id,
1323         subinventory_code,
1324         cycle_count_entry_id,
1325         source,
1326         approval_date,
1327         uom_code,
1328         system_inventory_qty,
1329         positive_adjustment_qty,
1330         negative_adjustment_qty,
1331         item_unit_cost,
1332         item_adj_unit_cost,
1333         hit_miss_pos,
1334         hit_miss_neg,
1335         exact_match   )
1336      SELECT  mcce.organization_id,
1337       mcce.inventory_item_id,
1338       mcce.cycle_count_header_id,
1339       to_char (mccc.abc_class_id),
1340       mmt_gtv.subinventory_code,
1341       to_char (mcce.cycle_count_entry_id),
1342       C_OPM_SOURCE,
1343       trunc (mcce.approval_date),
1344       msi.primary_uom_code,
1345       decode (mcce.count_uom_current,
1346       msi.primary_uom_code,
1347       mcce.system_quantity_current,
1348       inv_convert.inv_um_convert (      mcce.inventory_item_id,
1349                                         C_MMT_PRECISION,
1350                                         mcce.system_quantity_current,
1351                                         mcce.count_uom_current,
1352                                         msi.primary_uom_code,
1353                                         NULL,
1354                                         NULL)) system_inventory_qty,
1355       CASE WHEN sum (mmt_gtv.primary_quantity) > 0 THEN
1356                 sum (mmt_gtv.primary_quantity)
1357            ELSE   0
1358       END          positive_adjustment_qty,
1359       CASE WHEN sum (mmt_gtv.primary_quantity) < 0 THEN
1360                 -1 * sum (mmt_gtv.primary_quantity)
1361       ELSE   0
1362       END          negative_adjustment_qty ,
1363       decode (subs.asset_inventory,
1364                 C_EXPENSE_SUBINVENTORY, 0,
1365                 mcce.item_unit_cost)        item_unit_cost,
1366       decode (sum (mmt_gtv.primary_quantity),
1367                 0, decode (subs.asset_inventory,
1368                                 C_EXPENSE_SUBINVENTORY, 0,
1369                                 mcce.item_unit_cost),
1370                 nvl (sum (mmt_gtv.transaction_base_value)/
1371                         sum (mmt_gtv.primary_quantity), 0))        item_adj_unit_cost,
1372       decode (mmt_gtv.subinventory_code,
1373               mcce.subinventory, nvl (mccc.hit_miss_tolerance_positive,
1374                                       mcch.hit_miss_tolerance_positive),
1375               0),
1376       decode (mmt_gtv.subinventory_code,
1377               mcce.subinventory, nvl (mccc.hit_miss_tolerance_negative,
1378                                       mcch.hit_miss_tolerance_negative),
1379               0),
1380       decode (sum (mmt_gtv.primary_quantity),
1381               0, C_EXACT_MATCH,
1382               C_NO_MATCH)          exact_match
1383     FROM    mtl_cycle_count_entries mcce,
1384         mtl_cycle_count_headers mcch,
1385         mtl_cycle_count_items mcci,
1386         mtl_cycle_count_classes mccc,
1387         mtl_system_items_b msi,
1388         mtl_secondary_inventories subs,
1389 	-- below select is grouped at transaction_id, quantity level so that
1390 	-- quantity is summed correctly and then it can be joined with
1391 	-- mcce and other tables outside.
1392         (SELECT  mmt.organization_id,
1393                 mmt.transaction_id,
1394                 mmt.inventory_item_id,
1395                 mmt.cycle_count_id,
1396                 DECODE (mmt.transaction_type_id ,
1397                     5 , DECODE(GTV.subinventory_code,
1398                         MMT.subinventory_code, MMT.primary_quantity,
1399                         mmt.transfer_subinventory, -1* MMT.primary_quantity),mmt.primary_quantity)   primary_quantity,
1400                 DECODE (mmt.transaction_type_id ,
1401                     5 ,GTV.subinventory_code,
1402                     mmt.subinventory_code)  subinventory_code,
1403                 SUM (gtv.txn_base_value) transaction_base_value
1404         FROM    mtl_material_transactions mmt ,
1405                 (SELECT gt.*
1406                 FROM gmf_transaction_valuation gt,
1407                 opi_dbi_org_le_temp olt
1408                 WHERE olt.organization_id = gt.organization_id
1409                 AND olt.ledger_id = gt.ledger_id
1410                 AND olt.legal_entity_id = gt.legal_entity_id
1411                 AND olt.valuation_cost_type_id = gt.valuation_cost_type_id) gtv
1412         WHERE   gtv.event_class_code in ('MISC_TXN' , 'SUBINV_XFER')
1413          AND    gtv.event_type_code in ('CYCLE_COUNT_ADJ' , 'CYCLE_COUNT_XFER')
1414          AND    gtv.journal_line_type = 'INV'
1415          AND    gtv.transaction_source = 'INVENTORY'
1416          AND    gtv.transaction_date >= l_from_bound_date
1417 	 -- for final posted records consider within the bounds
1418 	 -- for draft posted records consider all the txns
1419          AND    DECODE( accounted_flag,
1420                         NULL, gtv.final_posting_date,
1421                        'D',s_global_start_date) < l_to_bound_date
1422          and    gtv.transaction_id = mmt.transaction_id
1423         GROUP BY
1424                 mmt.organization_id,
1425                 mmt.inventory_item_id,
1426                 mmt.cycle_count_id,
1427                 DECODE (mmt.transaction_type_id ,
1428                     5 , DECODE(GTV.subinventory_code,
1429                         MMT.subinventory_code, MMT.primary_quantity,
1430                         mmt.transfer_subinventory, -1* MMT.primary_quantity),mmt.primary_quantity),
1431                 DECODE (mmt.transaction_type_id ,
1432                     5 ,GTV.subinventory_code,
1433                     mmt.subinventory_code) ,
1434                 mmt.transaction_id) mmt_gtv
1435     WHERE   mmt_gtv.organization_id = msi.organization_id
1436       AND   mmt_gtv.inventory_item_id = msi.inventory_item_id
1437       AND   mmt_gtv.cycle_count_id = mcce.cycle_count_entry_id
1438       -- mmt records are created only after cycle count is approved
1439       -- hence its not possible that entry_status_code is not approved.
1440       -- it is ensured that all costed txns are collected
1441       AND   mcce.entry_status_code = C_COMPLETED_CCA_ENTRY -- 5
1442       AND   mcce.cycle_count_header_id = mcch.cycle_count_header_id
1443       AND   mcce.cycle_count_header_id = mcci.cycle_count_header_id
1444       AND   mcce.inventory_item_id = mcci.inventory_item_id
1445       AND   mcce.organization_id = mccc.organization_id
1446       AND   mcce.cycle_count_header_id = mccc.cycle_count_header_id
1447       AND   mcci.abc_class_id = mccc.abc_class_id
1448       AND   mmt_gtv.organization_id = subs.organization_id
1449       AND   mmt_gtv.subinventory_code = subs.secondary_inventory_name
1450     GROUP BY
1451             mcce.organization_id,
1452             mcce.inventory_item_id,
1453             mcce.cycle_count_header_id,
1454             mccc.abc_class_id,
1455             mmt_gtv.subinventory_code,
1456             mcce.cycle_count_entry_id,
1457             trunc (mcce.approval_date),
1458             msi.primary_uom_code,
1459             mcce.count_uom_current,
1460             mcce.system_quantity_current,
1461             subs.asset_inventory,
1462             mcce.item_unit_cost,
1463             mcce.subinventory,
1464             mccc.hit_miss_tolerance_positive,
1465             mcch.hit_miss_tolerance_positive,
1466             mcce.subinventory,
1467             mccc.hit_miss_tolerance_negative,
1468             mcch.hit_miss_tolerance_negative;
1469 
1470 
1471 
1472    RETURN;
1473 
1474 EXCEPTION
1475 
1476     WHEN NO_DATA_FOUND THEN
1477 
1478         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1479                                                      l_stmt_id));
1480 
1481         RAISE ADJUSTMENT_EXTR_ERROR;
1482 
1483 
1484     WHEN OTHERS THEN
1485 
1486         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1487                                                      l_stmt_id));
1488 
1489         RAISE ADJUSTMENT_EXTR_ERROR;
1490 
1491 END extract_process_adj_init;
1492 
1493 
1494 
1495 /* extract_exact_matches_init
1496 
1497     Extract the exact match entry data from the MTL_CYCLE_COUNT_ENTRIES
1498     table. Exact match data is easier to handle than adjustment entries
1499     because exact matches are approved on creation and there are no
1500     other transaction tables that need to be visited.
1501 
1502     We are only interested in entries completed after the global start
1503     date (i.e. entry_status_code = 5 and approval_date > global start date).
1504 
1505     The adjustment quantity is always 0 and hit/miss tolerances are not
1506     needed since all entries are, by definition, hits. We still need to join
1507     to MTL_CYCLE_COUNT_CLASSES to get the count and count class information.
1508 
1509     No need to join to MTL_CYCLE_COUNT_HEADERS as we don't need to
1510     get any tolerances.
1511 
1512     MCCE does not store quantities in the primary uom_code. If the
1513     transaction uom is not the same as the primary uom, all
1514     quantities will have to be converted to the primary uom.
1515 
1516     The date range being extracted is specified in the log table.
1517 
1518     However, since we are dealing with last_update_dates, we need to
1519     be sure that the dates in the log tables have timestamps so that
1520     we do not collect partially collected days again.
1521 
1522     The one special case is that we need to identify expense
1523     subinventories and set the item cost to 0 for all entries
1524     bearing those subinventory codes.
1525 
1526     ------------ R12 Changes
1527     Since Process exact matches will be extrracted in the same insert.
1528     Date bounds speific to organization based on first uncosted transaction
1529     cannot be applied. Hence we will use date bounds that are being used for
1530     the process adjustments. ie Collect all the exact matches for which
1531     MCCE.approval_date (MCCE.last_update_date) is between global
1532     start date and the initial program start date.
1533 
1534     Discrete Adjustments are collected only upto first uncosted transaction
1535     date. Hence exact matches and discrete cycle cout adjustments will be
1536     out of sync if there are uncosted transactions. Please refer bug 4395280.
1537 
1538 
1539     ------------
1540 
1541 
1542     Do not commit data. Let the wrapper coordinate committing of data.
1543 
1544     Parameters:
1545     None.
1546 
1547     History:
1548     Date        Author              Action
1549     01/15/04    Dinkar Gupta        Defined procedure.
1550     02/05/04    Dinkar Gupta        Added logic to join to the from and to
1551                                     transaction dates in the log table.
1552     06/22/05    Vishal Gupta	    Made changes on bounds.
1553 
1554 */
1555 PROCEDURE extract_exact_matches_init
1556 IS
1557     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_exact_matches_init';
1558     l_stmt_id	        NUMBER;
1559     l_from_bound_date   OPI_DBI_CONC_PROG_RUN_LOG.from_bound_date%type;
1560     l_to_bound_date     OPI_DBI_CONC_PROG_RUN_LOG.to_bound_date%type;
1561 
1562 BEGIN
1563 
1564     -- initialization block
1565     l_stmt_id := 0;
1566 
1567     SELECT from_bound_date, to_bound_date
1568     INTO l_from_bound_date, l_to_bound_date
1569     FROM OPI_DBI_CONC_PROG_RUN_LOG
1570     WHERE driving_table_code = C_LOG_GTV_DRV_TBL
1571       AND etl_type = C_ETL_TYPE
1572       AND load_type = C_LOAD_INIT;
1573 
1574 
1575     l_stmt_id := 10;
1576     -- This procedure will extract all all exact match data from MCCE
1577     -- and insert it into the staging table. For SQL logic, please refer
1578     -- to the procedure header
1579 
1580     -- Join condition justifications
1581     --
1582     -- to MCCC - on org, header and abc_class. The org is redundant,
1583     -- but this should allow use of U1 index on MCCC.
1584     -- Note the explicit check for the 0 adjustment quantity. This should
1585     -- ideally not be required but we found an example (which we have not
1586     -- been able to recreate) where there was an adjustment on a serialized
1587     -- item but the adjustment date was null in MCCE and
1588     -- MTL_CC_SERIAL_NUMBERS. To filter that case, we filter explicitly on
1589     -- on the quantity. Most likely, this is an OLTP bug that will be
1590     -- fixed.
1591     --
1592     -- to MCCI - on header and item. This should allow use of U1 index
1593     -- on MCCI.
1594     --
1595     -- to MCCE - on entry. This should allow use of U1 index.
1596     --  On entry_status_code. This is the leading column of the N6 index.
1597     --  Filter on last_update_date. This should use the newly created
1598     --  N8 (?) index.
1599     --
1600     -- no join needed to log - as we can extract GTV date bounds into variables
1601     -- .
1602 
1603 
1604 
1605     INSERT /*+ append parallel (opi_dbi_inv_cca_stg) */
1606     INTO opi_dbi_inv_cca_stg (
1607         organization_id,
1608         inventory_item_id,
1609         cycle_count_header_id,
1610         abc_class_id,
1611         subinventory_code,
1612         cycle_count_entry_id,
1613         source,
1614         approval_date,
1615         uom_code,
1616         system_inventory_qty,
1617         positive_adjustment_qty,
1618         negative_adjustment_qty,
1619         item_unit_cost,
1620         item_adj_unit_cost,
1621         hit_miss_pos,
1622         hit_miss_neg,
1623         exact_match)
1624     SELECT /*+ parallel(mcce) parallel(mcci) parallel(mccc)
1625                parallel(msi) parallel(subs) parallel(log)
1626                use_hash(mcci mccc msi subs) */
1627         mcce.organization_id,
1628         mcce.inventory_item_id,
1629         mcce.cycle_count_header_id,
1630         to_char (mccc.abc_class_id),
1631         mcce.subinventory,
1632         to_char (mcce.cycle_count_entry_id),
1633         decode(mp.process_enabled_flag,
1634                 'Y',C_OPM_SOURCE,
1635                 C_OPI_SOURCE )  source,
1636         trunc (mcce.approval_date),
1637         msi.primary_uom_code,
1638         decode (mcce.count_uom_current,
1639                 msi.primary_uom_code, mcce.system_quantity_current,
1640                 inv_convert.inv_um_convert
1641                     (mcce.inventory_item_id, C_MMT_PRECISION,
1642                      mcce.system_quantity_current, mcce.count_uom_current,
1643                      msi.primary_uom_code, NULL, NULL)),
1644         0,
1645         0,
1646         decode (subs.asset_inventory,
1647                 C_EXPENSE_SUBINVENTORY, 0,
1648                 mcce.item_unit_cost),
1649         0,
1650         NULL,
1651         NULL,
1652         C_EXACT_MATCH
1653       FROM  mtl_cycle_count_entries mcce,
1654             mtl_cycle_count_items mcci,
1655             mtl_cycle_count_classes mccc,
1656             mtl_system_items_b msi,
1657             mtl_secondary_inventories subs,
1658             mtl_parameters mp
1659       -- exact matches are approved at the time entry is completed
1660       -- hence it is not possible that status of a cycle count entry
1661       -- changes once the load is collected for that date range.
1662       WHERE mcce.last_update_date >= l_from_bound_date
1663         AND mcce.last_update_date < l_to_bound_date
1664         AND mcce.entry_status_code = C_COMPLETED_CCA_ENTRY
1665         AND mcce.organization_id = mp.organization_id
1666         AND mcce.adjustment_date IS NULL
1667         AND mcce.adjustment_quantity = 0
1668         AND mcce.cycle_count_header_id = mcci.cycle_count_header_id
1669         AND mcce.inventory_item_id = mcci.inventory_item_id
1670         AND mcce.organization_id = mccc.organization_id
1671         AND mcce.cycle_count_header_id = mccc.cycle_count_header_id
1672         AND mcci.abc_class_id = mccc.abc_class_id
1673         AND mcce.organization_id = msi.organization_id
1674         AND mcce.inventory_item_id = msi.inventory_item_id
1675         AND mcce.organization_id = subs.organization_id
1676         AND mcce.subinventory = subs.secondary_inventory_name;
1677 
1678 
1679         -- Do not commit here. Let the wrapper handle commit operations.
1680 
1681         RETURN;
1682 
1683 EXCEPTION
1684 
1685     WHEN NO_DATA_FOUND THEN
1686 
1687         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1688                                                      l_stmt_id));
1689 
1690         RAISE EXACT_MATCH_EXTR_ERROR;
1691 
1692     WHEN OTHERS THEN
1693 
1694         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1695                                                      l_stmt_id));
1696 
1697         RAISE EXACT_MATCH_EXTR_ERROR;
1698 
1699 END extract_exact_matches_init;
1700 
1701 /*  compute_cca_conv_rates_init
1702 
1703     Compute all the conversion rates for all distinct organization,
1704     transaction date pairs in the staging table. The date in the fact
1705     table is already without a timestamp i.e. trunc'ed.
1706 
1707     There are two conversion rates to be computed:
1708     1. Primary global
1709     2. Secondary global (if set up)
1710 
1711     The conversion rate work table was truncated during
1712     the initialization phase.
1713 
1714     Get the currency conversion rates based on the data in
1715     OPI_DBI_INV_CCA_STG using the fii_currency.get_global_rate_primary
1716     API for the primary global currency and
1717     fii_currency.get_global_rate_secondary for the secondary global currency.
1718     The primary currency API:
1719     1. finds the conversion rate if one exists.
1720     2. 'USD' always has a conversion rate of 1 (since it is global currency).
1721     3. returns -1 if there is no conversion rate on that date.
1722     4. returns -2 if the currency code is not found.
1723     5. returns -3 if the transaction_date is prior to 01-JAN-1999,
1724        the functional currency code is EUR and there is no EUR to USD
1725        conversion rate defined on 01-JAN-1999.
1726 
1727     The secondary currency API:
1728     1. Finds the global secondary currency rate if one exists.
1729     2. Returns a rate of 1 if the secondary currency has not been set up.
1730     3. Returns -1, -2, -3 in the same way as the primary currency code API.
1731 
1732     If the global and secondary currency codes and rate types are identical,
1733     do not call the secondary currency API. Instead update the secondary
1734     rates from the primary.
1735 
1736     If the secondary currency has not been set up, set the conversion rate
1737     to null.
1738 
1739     If any primary conversion rates are missing, throw an exception.
1740     If any secondary currency rates are missing (after the secondary
1741     currency has been set up) throw an exception.
1742 
1743     Need to commit data here due to insert+append.
1744 
1745     History:
1746     Date        Author              Action
1747     01/15/04    Dinkar Gupta        Defined procedure.
1748     05/11/04    Dinkar Gupta        Specializing this procedure for initial
1749                                     load.
1750     08/17/04    Dinkar Gupta        Added secondary currency support
1751 
1752 */
1753 
1754 PROCEDURE compute_cca_conv_rates_init (p_global_curr_code IN VARCHAR2,
1755                                        p_global_rate_type IN VARCHAR2)
1756 
1757 IS
1758 
1759     l_proc_name CONSTANT VARCHAR2 (60) := 'compute_cca_conv_rates_init';
1760     l_stmt_id NUMBER;
1761 
1762     -- Cursor to see if any rates are missing. See below for details
1763     CURSOR invalid_rates_exist_csr IS
1764         SELECT 1
1765           FROM opi_dbi_inv_cca_conv
1766           WHERE (   nvl (conversion_rate, -999) < 0
1767                  OR nvl (sec_conversion_rate, 999) < 0)
1768             AND rownum < 2;
1769 
1770     invalid_rates_exist_rec invalid_rates_exist_csr%ROWTYPE;
1771 
1772     -- Set up a cursor to get all the invalid rates.
1773     -- By the logic of the fii_currency.get_global_rate_primary
1774     -- and fii_currency.get_global_rate_secondary APIs, the returned value
1775     -- is -ve if no rate exists:
1776     -- -1 for dates with no rate.
1777     -- -2 for unrecognized conversion rates.
1778     -- -3 for missing EUR to USD rates on 01-JAN-1999 when the
1779     --    transaction_date is prior to 01-JAN-1999 (when the EUR
1780     --    officially went into circulation).
1781     --
1782     -- However, with the secondary currency, the null rate means it
1783     -- has not been setup and should therefore not be reported as an
1784     -- error.
1785     --
1786     -- Also, cross check with the org-date pairs in the staging table,
1787     -- in case some orgs never had a functional currency code defined.
1788     CURSOR invalid_rates_csr (p_pri_sec_curr_same NUMBER) IS
1789         SELECT /*+ parallel (compare) */
1790         DISTINCT
1791             report_order,
1792             curr_code,
1793             rate_type,
1794             approval_date,
1795             func_currency_code
1796           FROM (
1797                 SELECT /*+ parallel (conv) parallel (mp) parallel (to_conv) */
1798                 DISTINCT
1799                     s_global_curr_code curr_code,
1800                     s_global_rate_type rate_type,
1801                     1 report_order, -- ordering global currency first
1802                     mp.organization_code,
1803                     decode (conv.conversion_rate,
1804                             C_EURO_MISSING_AT_START, C_EURO_START_DATE,
1805                             conv.approval_date) approval_date,
1806                     conv.func_currency_code
1807               FROM opi_dbi_inv_cca_conv conv,
1808                    mtl_parameters mp,
1809                   (SELECT /*+ parallel (opi_dbi_inv_cca_stg) */
1810                    DISTINCT organization_id, approval_date
1811                      FROM opi_dbi_inv_cca_stg) to_conv
1812               WHERE nvl (conv.conversion_rate, -999) < 0 -- null is not fine
1813                 AND mp.organization_id = to_conv.organization_id
1814                 AND conv.approval_date (+) = to_conv.approval_date
1815                 AND conv.organization_id (+) = to_conv.organization_id
1816             UNION ALL
1817             SELECT /*+ parallel (conv) parallel (mp) parallel (to_conv) */
1818             DISTINCT
1819                     s_secondary_curr_code curr_code,
1820                     s_secondary_rate_type rate_type,
1821                     decode (p_pri_sec_curr_same,
1822                             1, 1,
1823                             2) report_order, --ordering secondary currency next
1824                     mp.organization_code,
1825                     decode (conv.sec_conversion_rate,
1826                             C_EURO_MISSING_AT_START, C_EURO_START_DATE,
1827                             conv.approval_date) approval_date,
1828                     conv.func_currency_code
1829               FROM opi_dbi_inv_cca_conv conv,
1830                    mtl_parameters mp,
1831                   (SELECT /*+ parallel (opi_dbi_inv_cca_stg) */
1832                    DISTINCT organization_id, approval_date
1833                      FROM opi_dbi_inv_cca_stg) to_conv
1834               WHERE nvl (conv.sec_conversion_rate, 999) < 0 -- null is fine
1835                 AND mp.organization_id = to_conv.organization_id
1836                 AND conv.approval_date (+) = to_conv.approval_date
1837                 AND conv.organization_id (+) = to_conv.organization_id)
1838           compare
1839           ORDER BY
1840                 report_order ASC,
1841                 approval_date,
1842                 func_currency_code;
1843 
1844 
1845     -- Flag to ensure all rates have been found.
1846     l_all_rates_found BOOLEAN;
1847 
1848     -- Boolean to check if the primary and secondary currencies are the
1849     -- same
1850     l_pri_sec_curr_same NUMBER;
1851 
1852 BEGIN
1853 
1854     -- initialization block
1855     l_stmt_id := 0;
1856     l_all_rates_found := true;
1857     l_pri_sec_curr_same := 0;
1858 
1859     l_stmt_id := 5;
1860     -- check if the primary and secondary currencies and rate types are
1861     -- identical.
1862     IF (s_global_curr_code = nvl (s_secondary_curr_code, '---') AND
1863         s_global_rate_type = nvl (s_secondary_rate_type, '---') ) THEN
1864         l_pri_sec_curr_same := 1;
1865     END IF;
1866 
1867 
1868     l_stmt_id := 10;
1869     -- Get all the distinct organization and date pairs and the
1870     -- base currency codes for the orgs into the conversion rates
1871     -- work table.
1872 
1873     -- Use the fii_currency.get_global_rate_primary function to get the
1874     -- conversion rate given a currency code and a date.
1875     -- The function returns:
1876     -- 1 for currency code of 'USD' which is the global currency
1877     -- -1 for dates for which there is no currency conversion rate
1878     -- -2 for unrecognized currency conversion rates
1879     -- -3 for missing EUR to USD rates on 01-JAN-1999 when the
1880     --    transaction_date is prior to 01-JAN-1999 (when the EUR
1881     --    officially went into circulation).
1882 
1883     -- Use the fii_currency.get_global_rate_secondary to get the secondary
1884     -- global rate. If the secondary currency has not been set up,
1885     -- make the rate null. If the secondary currency/rate types are the
1886     -- same as the primary, don't call the API but rather use an update
1887     -- statement followed by the insert.
1888 
1889     -- By selecting distinct org and currency code from the gl_set_of_books
1890     -- and hr_organization_information, take care of duplicate codes.
1891 
1892     INSERT /*+ append parallel (opi_dbi_inv_cca_conv) */
1893     INTO opi_dbi_inv_cca_conv (
1894         organization_id,
1895         func_currency_code,
1896         approval_date,
1897         conversion_rate,
1898         sec_conversion_rate)
1899     SELECT /*+ parallel (to_conv) parallel (curr_codes) */
1900         to_conv.organization_id,
1901         curr_codes.currency_code,
1902         to_conv.approval_date,
1903         decode (curr_codes.currency_code,
1904                 s_global_curr_code, 1,
1905                 fii_currency.get_global_rate_primary (
1906                                     curr_codes.currency_code,
1907                                     to_conv.approval_date) ),
1908         decode (s_secondary_curr_code,
1909                 NULL, NULL,
1910                 curr_codes.currency_code, 1,
1911                 decode (l_pri_sec_curr_same,
1912                         1, C_PRI_SEC_CURR_SAME_MARKER,
1913                         fii_currency.get_global_rate_secondary (
1914                             curr_codes.currency_code,
1915                             to_conv.approval_date)))
1916       FROM
1917         (SELECT /*+ parallel (opi_dbi_inv_cca_stg) */
1918          DISTINCT organization_id, approval_date
1919            FROM opi_dbi_inv_cca_stg) to_conv,
1920         (SELECT /*+ leading (hoi) full (hoi) use_hash (gsob)
1921                     parallel (hoi) parallel (gsob)*/
1922          DISTINCT hoi.organization_id, gsob.currency_code
1923            FROM hr_organization_information hoi,
1924                 gl_sets_of_books gsob
1925            WHERE hoi.org_information_context  = 'Accounting Information'
1926              AND hoi.org_information1  = to_char(gsob.set_of_books_id))
1927         curr_codes
1928       WHERE curr_codes.organization_id  = to_conv.organization_id;
1929 
1930     l_stmt_id := 15;
1931     commit;   -- due to insert+append
1932 
1933     l_stmt_id := 20;
1934     -- if the primary and secondary currency codes are the same, then
1935     -- update the secondary with the primary
1936     IF (l_pri_sec_curr_same = 1) THEN
1937 
1938         l_stmt_id := 30;
1939         UPDATE /*+ parallel (opi_dbi_inv_cca_conv) */ opi_dbi_inv_cca_conv
1940         SET sec_conversion_rate = conversion_rate;
1941 
1942         -- safe to commit, as before
1943         l_stmt_id := 40;
1944         commit;
1945 
1946     END IF;
1947 
1948     -- Check that all rates have been found and are non-negative.
1949     -- If there is a problem, notify user.
1950     l_stmt_id := 50;
1951     OPEN invalid_rates_exist_csr;
1952     FETCH invalid_rates_exist_csr INTO invalid_rates_exist_rec;
1953     IF (invalid_rates_exist_csr%FOUND) THEN
1954 
1955         -- print the header out
1956         BIS_COLLECTION_UTILITIES.writeMissingRateHeader;
1957 
1958         -- all rates not found
1959         l_all_rates_found := false;
1960 
1961 
1962         FOR invalid_rate_rec IN invalid_rates_csr (l_pri_sec_curr_same)
1963         LOOP
1964 
1965             BIS_COLLECTION_UTILITIES.writeMissingRate(
1966                invalid_rate_rec.rate_type,
1967                invalid_rate_rec.func_currency_code,
1968                invalid_rate_rec.curr_code,
1969                invalid_rate_rec.approval_date);
1970 
1971         END LOOP;
1972     END IF;
1973 
1974     l_stmt_id := 55;
1975     CLOSE invalid_rates_exist_csr;
1976 
1977     -- If all rates not found raise an exception
1978     l_stmt_id := 60;
1979     IF (l_all_rates_found = FALSE) THEN
1980         RAISE MISSING_CONV_RATES;
1981     END IF;
1982 
1983     RETURN;
1984 
1985 EXCEPTION
1986 
1987     WHEN MISSING_CONV_RATES THEN
1988 
1989         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
1990                                             (MISSING_CONV_RATES_MESG,
1991                                              l_proc_name, l_stmt_id));
1992         RAISE CONV_RATES_ERROR;
1993 
1994 
1995     WHEN OTHERS THEN
1996 
1997         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
1998                                                      l_stmt_id));
1999 
2000         RAISE CONV_RATES_ERROR;
2001 
2002 
2003 END compute_cca_conv_rates_init;
2004 
2005 
2006 /* populate_fact_init
2007 
2008     Move all the staging table data into the fact table. The granularity
2009     of the data remains the same as the staging table i.e. the
2010     cycle count entry level.
2011 
2012     The fact joins to the conversion rates table to compute the values
2013     in both the functional currency and global currency.
2014 
2015     Quantities in the staging table are already the primary UOM.
2016 
2017     Adjustment values are computed using the item_adj_unit_cost which
2018     is derived from the MTA base_transaction_value. Thus reported
2019     adjustment values always match MTA.
2020 
2021     System inventory values are computed using the item_unit_cost which
2022     is the cost of the item at the time when the entry was first entered.
2023     Thus system inventory value matches that reported in Oracle Forms.
2024     This is to work around the issues of layered costing in LIFO/FIFO
2025     orgs (bug 3471888).
2026 
2027     Use the absolute value of system quantity to compute hit/miss because
2028     the system quantity can be negative. The tolerances however are
2029     defined as positive numbers. The sign and value of the adjustment
2030     are otherwise correct to allow for using absolute value of
2031     system quantity.
2032 
2033     The computation of whether an entry is a hit or a miss is done in
2034     this step.
2035     1. If the entry is an exact match, it is a hit.
2036     2. If the +ve and -ve hit/miss tolerances are null, it is a hit.
2037     3. If the system_inventory_qty is 0:
2038         - if the adjustment_qty is non zero, it is a miss.
2039         - else it is a hit.
2040     4. If the adjustment is +ve:
2041         - if the +ve tolerance is null, it is a hit.
2042         - else (adjustment_qty/system_inventory_qty) <=
2043             (+ve tolerance)/100, it is a hit.
2044         This check handles the divide by 0 case.
2045     5. If the adjustment is -ve:
2046         - if the -ve tolerance is null, it is a hit.
2047         - else (adjustment_qty/system_inventory_qty) <=
2048             (-ve tolerance)/100, it is a hit. [since both the negative
2049             adjustment quantities and tolerances are reported as
2050             positive numbers.]
2051     6. Any other case is a miss.
2052 
2053     Do not commit anything in this step. Let the wrapper handle that.
2054 
2055     History:
2056     Date        Author              Action
2057     01/15/04    Dinkar Gupta        Defined procedure.
2058     02/09/04    Dinkar Gupta        Used absolute value of
2059                                     system inventory quantity
2060                                     to compute hit/miss.
2061     03/10/04    Dinkar Gupta        Used item_cost from MCCE for system
2062                                     inventory value and cost from MTA
2063                                     for adjustment value to account for
2064                                     for LIFO/FIFO org layered costing.
2065     08/17/04    Dinkar Gupta        Added secondary currency support
2066 */
2067 
2068 PROCEDURE populate_fact_init
2069 IS
2070 
2071     l_proc_name CONSTANT VARCHAR2(40) := 'populate_fact_init';
2072     l_stmt_id NUMBER;
2073 
2074 BEGIN
2075 
2076     -- initialization block
2077     l_stmt_id := 0;
2078 
2079     l_stmt_id := 10;
2080     -- Insert data into the fact table. For explanation of logic,
2081     -- see procedure header.
2082     INSERT /*+ append parallel(opi_dbi_inv_cca_f) */
2083     INTO opi_dbi_inv_cca_f (
2084         organization_id,
2085         inventory_item_id,
2086         cycle_count_header_id,
2087         abc_class_id,
2088         subinventory_code,
2089         cycle_count_entry_id,
2090         source,
2091         approval_date,
2092         uom_code,
2093         system_inventory_qty,
2094         system_inventory_val_b,
2095         system_inventory_val_g,
2096         system_inventory_val_sg,
2097         positive_adjustment_qty,
2098         positive_adjustment_val_b,
2099         positive_adjustment_val_g,
2100         positive_adjustment_val_sg,
2101         negative_adjustment_qty,
2102         negative_adjustment_val_b,
2103         negative_adjustment_val_g,
2104         negative_adjustment_val_sg,
2105         conversion_rate,
2106         sec_conversion_rate,
2107         item_unit_cost,
2108         hit_or_miss,
2109         exact_match,
2110         last_update_date,
2111         last_updated_by,
2112         last_update_login,
2113         creation_date,
2114         created_by,
2115         request_id,
2116         program_application_id,
2117         program_id,
2118         program_update_date)
2119     SELECT /*+ parallel(stg) parallel (conv) use_hash (stg conv)*/
2120         stg.organization_id,
2121         stg.inventory_item_id,
2122         stg.cycle_count_header_id,
2123         stg.abc_class_id,
2124         stg.subinventory_code,
2125         stg.cycle_count_entry_id,
2126         stg.source,
2127         stg.approval_date,
2128         stg.uom_code,
2129         stg.system_inventory_qty,
2130         stg.system_inventory_qty * stg.item_unit_cost,
2131         stg.system_inventory_qty * stg.item_unit_cost *
2132             conv.conversion_rate,
2133         stg.system_inventory_qty * stg.item_unit_cost *
2134             conv.sec_conversion_rate,
2135         stg.positive_adjustment_qty,
2136         stg.positive_adjustment_qty * stg.item_adj_unit_cost,
2137         stg.positive_adjustment_qty * stg.item_adj_unit_cost *
2138             conv.conversion_rate,
2139         stg.positive_adjustment_qty * stg.item_adj_unit_cost *
2140             conv.sec_conversion_rate,
2141         stg.negative_adjustment_qty,
2142         stg.negative_adjustment_qty * stg.item_adj_unit_cost,
2143         stg.negative_adjustment_qty * stg.item_adj_unit_cost *
2144             conv.conversion_rate,
2145         stg.negative_adjustment_qty * stg.item_adj_unit_cost *
2146             conv.sec_conversion_rate,
2147         conv.conversion_rate,
2148         conv.sec_conversion_rate,
2149         stg.item_unit_cost,
2150         CASE
2151             WHEN stg.exact_match = C_EXACT_MATCH THEN
2152                 C_HIT
2153             WHEN stg.hit_miss_pos IS NULL AND stg.hit_miss_neg IS NULL THEN
2154                 C_HIT
2155             WHEN stg.hit_miss_pos IS NULL AND
2156                  stg.positive_adjustment_qty > 0 THEN
2157                 C_HIT
2158             WHEN stg.hit_miss_neg IS NULL AND
2159                  stg.negative_adjustment_qty > 0 THEN
2160                 C_HIT
2161             WHEN stg.system_inventory_qty = 0 THEN
2162                 CASE
2163                     WHEN stg.positive_adjustment_qty = 0 AND
2164                          stg.negative_adjustment_qty = 0 THEN
2165                         C_HIT
2166                     ELSE
2167                         C_MISS
2168                 END
2169             WHEN stg.positive_adjustment_qty > 0 AND
2170                  (stg.positive_adjustment_qty/
2171                   abs (stg.system_inventory_qty)) <=
2172                  (stg.hit_miss_pos/100) THEN
2173                 C_HIT
2174             WHEN stg.negative_adjustment_qty > 0 AND
2175                  (stg.negative_adjustment_qty/
2176                   abs (stg.system_inventory_qty)) <=
2177                  (stg.hit_miss_neg/100) THEN
2178                 C_HIT
2179             ELSE
2180                 C_MISS
2181             END,
2182         stg.exact_match,
2183         sysdate,
2184         s_user_id,
2185         s_login_id,
2186         sysdate,
2187         s_user_id,
2188         s_request_id,
2189         s_program_application_id,
2190         s_program_id,
2191         sysdate
2192       FROM  opi_dbi_inv_cca_stg stg,
2193             opi_dbi_inv_cca_conv conv
2194       WHERE stg.organization_id = conv.organization_id
2195         AND stg.approval_date = conv.approval_date;
2196 
2197     -- Do not commit here. Let the wrapper handle that.
2198 
2199     RETURN;
2200 
2201 EXCEPTION
2202 
2203     WHEN OTHERS THEN
2204 
2205         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
2206                                                      l_stmt_id));
2207 
2208         RAISE FACT_MERGE_ERROR;
2209 
2210 END populate_fact_init;
2211 
2212 
2213 
2214 
2215 /**************************************************
2216 * Incremental Load Procedure Definitions
2217 **************************************************/
2218 
2219 /* run_incr_load
2220 
2221     Wrapper routine for the incremental load of the cycle count accuracy ETL.
2222 
2223     Parameters:
2224     retcode - 0 on successful completion, -1 on error and 1 for warning.
2225     errbuf - empty on successful completion, message on error or warning
2226 
2227     History:
2228     Date        Author              Action
2229     01/12/04    Dinkar Gupta        Defined procedure.
2230     03/04/04    Dinkar Gupta        Added call to OPM package.
2231 */
2232 PROCEDURE run_incr_load (errbuf OUT NOCOPY VARCHAR2,
2233                          retcode OUT NOCOPY NUMBER)
2234 
2235 IS
2236     l_proc_name CONSTANT VARCHAR2 (40) := 'run_incr_load';
2237     l_stmt_id NUMBER;
2238 
2239 BEGIN
2240 
2241     -- initialization block
2242     l_stmt_id := 0;
2243 
2244     l_stmt_id := 10;
2245     -- Check for DBI global parameter setup, initialize file scope variables,
2246     -- check for bounds and truncate the needed tables.
2247     BIS_COLLECTION_UTILITIES.PUT_LINE ('Initializing cycle count incremental load ...');
2248     cca_initialize_incr ();
2249 
2250     l_stmt_id := 20;
2251     -- Set up the bounds for Cycle Count accuracy in the log table.
2252     BIS_COLLECTION_UTILITIES.PUT_LINE (
2253         'Setting up bounds for discrete manufacturing organzations ...');
2254     -- return status not speified in the procedure
2255     OPI_DBI_BOUNDS_PKG.MAINTAIN_OPI_DBI_LOGS (	p_etl_type=> C_ETL_TYPE,
2256 						p_load_type=> C_LOAD_INCR);
2257     l_stmt_id := 30;
2258     -- Extract the adjustment entry data from MMT/MTA using the
2259     -- bounds just set up.
2260     BIS_COLLECTION_UTILITIES.PUT_LINE (
2261         'Extracting cycle count adjustment information for discrete manufacturing orgs ...');
2262     extract_discrete_adj_incr (s_global_start_date);
2263 
2264     l_stmt_id := 40;
2265     -- Due to the bulk insert, commit before
2266     -- inputting more data to the staging table.
2267     commit;
2268 
2269     l_stmt_id := 45;
2270     -- Call API to load ledger data into Global temp table
2271     -- This temp table will be joined to extract process adjustments
2272     BIS_COLLECTION_UTILITIES.PUT_LINE (
2273         'Loading Ledger data into temp table ...');
2274     OPI_DBI_BOUNDS_PKG.load_opm_org_ledger_data;
2275 
2276      l_stmt_id := 47;
2277     -- Committing the data. Since the temp table is made with On Commit preserve rows
2278     -- there will be no problem.
2279     commit;
2280 
2281     l_stmt_id := 50;
2282     -- Extract the adjustment entry data from MMT/MTA using the
2283     -- bounds just set up.
2284     BIS_COLLECTION_UTILITIES.PUT_LINE (
2285         'Extracting cycle count adjustment information for process manufacturing orgs ...');
2286     extract_process_adj_incr (s_global_start_date);
2287 
2288     l_stmt_id := 60;
2289     -- Due to the bulk insert, commit before
2290     -- inputting more data to the staging table.
2291     commit;
2292 
2293     l_stmt_id := 70;
2294     -- Extract the exact matches entry data from MCCE. Collect all rows
2295     -- with last_update_date greater than the global start date.
2296     BIS_COLLECTION_UTILITIES.PUT_LINE (
2297         'Extracting cycle count exact match information for discrete and process manufacturing organizations ...');
2298     extract_exact_matches_incr ();
2299 
2300     l_stmt_id := 80;
2301     -- Due to the bulk insert, commit before moving ahead.
2302     commit;
2303 
2304     l_stmt_id := 90;
2305     -- Compute the conversion rates for all org/date pairs in the
2306     -- staging table. This API will now commit, due to an
2307     -- insert+append hint.
2308     BIS_COLLECTION_UTILITIES.PUT_LINE (
2309         'Computing conversion rates for all extracted cycle counting data ...');
2310     compute_cca_conv_rates_incr (s_global_curr_code, s_global_rate_type);
2311 
2312     l_stmt_id := 100;
2313     -- Commit the conversion rates found before finally merging all
2314     -- data to the fact table.
2315     commit;
2316 
2317     l_stmt_id := 110;
2318     -- Insert all the data into the fact table in one shot.
2319     BIS_COLLECTION_UTILITIES.PUT_LINE ('Inserting data into the fact table ...');
2320     populate_fact_incr ();
2321 
2322 
2323     l_stmt_id := 120;
2324     -- Update the bounds table
2325     BIS_COLLECTION_UTILITIES.PUT_LINE ('Updating run time bounds for next run ...');
2326     -- return status not speified in the procedure
2327     OPI_DBI_BOUNDS_PKG.SET_LOAD_SUCCESSFUL(C_ETL_TYPE, C_LOAD_INCR);
2328 
2329 
2330     l_stmt_id := 130;
2331     -- Truncate the staging table, commit the data to the fact table
2332     -- and update the bounds related to cycle counts in one database
2333     -- transaction for consistency.
2334     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2335                        'opi_dbi_inv_cca_stg');
2336 
2337 
2338     -- return successfully
2339     retcode := C_SUCCESS;
2340     errbuf := '';
2341 
2342     BIS_COLLECTION_UTILITIES.PUT_LINE ('Cycle count data extracted into the fact table successfully.');
2343 
2344     RETURN;
2345 
2346 EXCEPTION
2347 
2348 
2349 
2350     WHEN INITIALIZATION_ERROR THEN
2351 
2352         rollback;
2353 
2354         -- report the error
2355         retcode := C_ERROR;
2356         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2357         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2358                                             (INITIALIZATION_ERROR_MESG,
2359                                              l_proc_name, l_stmt_id));
2360         RETURN;
2361 
2362 
2363     WHEN BOUNDS_SETUP_ERROR THEN
2364 
2365         rollback;
2366 
2367         -- report the error
2368         retcode := C_ERROR;
2369         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2370         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2371                                             (BOUNDS_SETUP_ERROR_MESG,
2372                                              l_proc_name, l_stmt_id));
2373         RETURN;
2374 
2375 
2376     WHEN ADJUSTMENT_EXTR_ERROR THEN
2377 
2378         rollback;
2379 
2380         -- report the error
2381         retcode := C_ERROR;
2382         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2383         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2384                                             (ADJUSTMENT_EXTR_ERROR_MESG,
2385                                              l_proc_name, l_stmt_id));
2386         RETURN;
2387 
2388 
2389     WHEN EXACT_MATCH_EXTR_ERROR THEN
2390 
2391         rollback;
2392 
2393         -- Truncate the staging table because extraction failed midway.
2394         -- In the next run, all previously extracted and
2395         -- adjustment entry data will be re-extracted.
2396         EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2397                            'opi_dbi_inv_cca_stg');
2398 
2399         -- report the error
2400         retcode := C_ERROR;
2401         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2402         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2403                                             (EXACT_MATCH_EXTR_ERROR_MESG,
2404                                              l_proc_name, l_stmt_id));
2405         RETURN;
2406 
2407 
2408     WHEN BOUNDS_UPDATE_ERROR THEN
2409 
2410         rollback;
2411 
2412         -- Truncate the staging table because extraction failed midway.
2413         -- In the next run, all previously extracted exact match and
2414         -- adjustment entry data will be re-extracted.
2415         EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2416                            'opi_dbi_inv_cca_stg');
2417 
2418         -- report the error
2419         retcode := C_ERROR;
2420         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2421         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2422                                             (BOUNDS_UPDATE_ERROR_MESG,
2423                                              l_proc_name, l_stmt_id));
2424         RETURN;
2425 
2426 
2427 
2428     WHEN CONV_RATES_ERROR THEN
2429 
2430         rollback;
2431 
2432         -- report the error
2433         retcode := C_ERROR;
2434         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2435         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2436                                             (CONV_RATES_ERROR_MESG,
2437                                              l_proc_name, l_stmt_id));
2438         RETURN;
2439 
2440 
2441     WHEN FACT_MERGE_ERROR THEN
2442 
2443         rollback;
2444 
2445         -- report the error
2446         retcode := C_ERROR;
2447         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2448         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2449                                             (FACT_MERGE_ERROR_MESG,
2450                                              l_proc_name, l_stmt_id));
2451         RETURN;
2452 
2453     WHEN OPM_EXTRACTION_ERROR THEN
2454 
2455         rollback;
2456 
2457         -- report the error
2458         retcode := C_ERROR;
2459         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2460         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2461                                             (OPM_EXTRACTION_ERROR_MESG,
2462                                              l_proc_name, l_stmt_id));
2463         RETURN;
2464 
2465     WHEN OTHERS THEN
2466 
2467         rollback;
2468 
2469         -- report the error
2470         retcode := C_ERROR;
2471         errbuf := 'Inventory Cycle Count Accuracy ETL incremental load terminated with errors. Please check the concurrent program log file for errors.';
2472 
2473         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
2474                                                      l_stmt_id));
2475 
2476         RETURN;
2477 
2478 END run_incr_load;
2479 
2480 
2481 /* cca_initialize_incr
2482 
2483     Check that the primary currency code and global start date have been
2484     set up.
2485 
2486     Get the OPI schema info.
2487 
2488     Check if the log table has rows created for type = 'CCA' to determine
2489     if at least the initial load has already been run.
2490 
2491     Truncate all the conversion rates table.
2492 
2493     If the transaction_id bounds are not null for all orgs, then
2494     an error occurred during the extraction in the previous run. If so,
2495     truncate the staging table as the partial extraction from last time
2496     will be redone all over again in this run.
2497 
2498     Note: Do not check to see if this initial load has been run previously.
2499 
2500     History:
2501     Date        Author              Action
2502     01/19/04    Dinkar Gupta        Defined procedure.
2503     04/08/04    Dinkar Gupta        Changed the bounds checking logic to
2504                                     only look for rows with missing
2505                                     from_transaction_ids. In case MMT was
2506                                     empty in the initial load, this will
2507                                     still behave properly.
2508     08/17/04    Dinkar Gupta        Added Secondary Currency support.
2509 */
2510 
2511 PROCEDURE cca_initialize_incr
2512 IS
2513 
2514     l_proc_name CONSTANT VARCHAR2 (40) := 'cca_initialize_incr';
2515     l_stmt_id NUMBER;
2516 
2517 
2518 BEGIN
2519 
2520     -- initialization block
2521     l_stmt_id := 0;
2522 
2523 
2524     l_stmt_id := 10;
2525     -- Check for the primary currency code and global start date setup.
2526     -- These two parameters must be set up prior to any DBI load.
2527     IF (NOT (check_global_setup ())) THEN
2528         RAISE GLOBAL_SETUP_MISSING;
2529     END IF;
2530 
2531     l_stmt_id := 20;
2532     -- Obtain the OPI schema name to allow truncation of various tables
2533     -- get session parameters
2534     IF (NOT (fnd_installation.get_app_info('OPI', s_status, s_industry,
2535                                            s_opi_schema))) THEN
2536         RAISE SCHEMA_INFO_NOT_FOUND;
2537     END IF;
2538 
2539 
2540     -- Get the global start date
2541     l_stmt_id := 30;
2542     s_global_start_date := trunc (bis_common_parameters.get_global_start_date);
2543     IF (s_global_start_date IS NULL) THEN
2544         RAISE GLOBAL_START_DATE_NULL;
2545     END IF;
2546 
2547 
2548     l_stmt_id := 40;
2549     -- Get the DBI global currency code
2550     s_global_curr_code := bis_common_parameters.get_currency_code;
2551 
2552     l_stmt_id := 50;
2553     IF (s_global_curr_code IS NULL) THEN
2554         RAISE NO_GLOBAL_CURR_CODE;
2555     END IF;
2556 
2557 
2558     l_stmt_id := 60;
2559     -- Get the DBI Global rate type
2560     s_global_rate_type := bis_common_parameters.get_rate_type;
2561 
2562     l_stmt_id := 70;
2563     IF (s_global_rate_type IS NULL) THEN
2564         RAISE NO_GLOBAL_RATE_TYPE;
2565     END IF;
2566 
2567     l_stmt_id := 80;
2568     -- Get the DBI secondary currency code
2569     s_secondary_curr_code := bis_common_parameters.get_secondary_currency_code;
2570 
2571     l_stmt_id := 90;
2572     -- Get the DBI Global rate type
2573     s_secondary_rate_type := bis_common_parameters.get_secondary_rate_type;
2574 
2575     l_stmt_id := 100;
2576     IF (    (s_secondary_curr_code IS NULL AND
2577              s_secondary_rate_type IS NOT NULL)
2578          OR (s_secondary_curr_code IS NOT NULL AND
2579              s_secondary_rate_type IS NULL) ) THEN
2580         RAISE SEC_CURR_SETUP_INVALID;
2581     END IF;
2582 
2583     l_stmt_id := 110;
2584     -- Since bounds are now being updated only when the merge to
2585     -- the fact is complete and are being committed using the truncate
2586     -- on the staging table, just ensure that the staging table is
2587     -- truncated.
2588     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2589                        'opi_dbi_inv_cca_stg');
2590 
2591 
2592     -- Truncate the following tables (in case of exceptions, nothing
2593     -- special to do here because it is a database error):
2594 
2595     l_stmt_id := 120;
2596     -- Conversion rates table
2597     EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2598                        'opi_dbi_inv_cca_conv');
2599 
2600     -- Not using
2601     l_stmt_id := 130;
2602     -- Temp table for bounds computation
2603     --EXECUTE IMMEDIATE ('TRUNCATE TABLE ' || s_opi_schema || '.' ||
2604      --                  'opi_dbi_inv_value_log_tmp');
2605 
2606 
2607     l_stmt_id := 140;
2608     -- User and login id's
2609     s_user_id := nvl(fnd_global.user_id, -1);
2610     s_login_id := nvl(fnd_global.login_id, -1);
2611     s_program_id := nvl(fnd_global.conc_program_id, -1);
2612     s_program_login_id := nvl(fnd_global.conc_login_id , -1);
2613     s_program_application_id := nvl(fnd_global.prog_appl_id , -1);
2614     s_request_id := nvl(fnd_global.conc_request_id, -1);
2615 
2616     RETURN;
2617 
2618 EXCEPTION
2619 
2620     WHEN GLOBAL_SETUP_MISSING THEN
2621 
2622         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (GLOBAL_SETUP_MISSING_MESG,
2623                                                      l_proc_name, l_stmt_id));
2624         RAISE INITIALIZATION_ERROR;
2625 
2626     WHEN SCHEMA_INFO_NOT_FOUND THEN
2627 
2628         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2629                                             (SCHEMA_INFO_NOT_FOUND_MESG,
2630                                              l_proc_name, l_stmt_id));
2631         RAISE INITIALIZATION_ERROR;
2632 
2633 
2634     WHEN GLOBAL_START_DATE_NULL THEN
2635 
2636         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2637                                             (GLOBAL_START_DATE_NULL_MESG,
2638                                              l_proc_name, l_stmt_id));
2639         RAISE INITIALIZATION_ERROR;
2640 
2641 
2642     WHEN NO_GLOBAL_CURR_CODE THEN
2643 
2644         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2645                                             (NO_GLOBAL_CURR_CODE_MESG,
2646                                              l_proc_name, l_stmt_id));
2647         RAISE INITIALIZATION_ERROR;
2648 
2649 
2650     WHEN NO_GLOBAL_RATE_TYPE THEN
2651 
2652         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2653                                             (NO_GLOBAL_RATE_TYPE_MESG,
2654                                              l_proc_name, l_stmt_id));
2655         RAISE INITIALIZATION_ERROR;
2656 
2657 
2658     WHEN SEC_CURR_SETUP_INVALID THEN
2659         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
2660                                             (SEC_CURR_SETUP_INVALID_MESG,
2661                                              l_proc_name, l_stmt_id));
2662 
2663         RAISE INITIALIZATION_ERROR;
2664 
2665     WHEN OTHERS THEN
2666 
2667         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
2668                                                      l_stmt_id));
2669 
2670         RAISE INITIALIZATION_ERROR;
2671 
2672 
2673 END cca_initialize_incr;
2674 
2675 
2676 /* extract_discrete_adj_incr
2677 
2678     Extract discrete adjustment entry data from MTL_CYCLE_COUNT_ENTRIES (MCCE),
2679     MMT and MTA. Adjustments can get costed well after approval and
2680     interim cost updates may cause the values recorded in MCCE to
2681     be different. Thus we need to get the cost associated to the item
2682     using the value in MTA so that the reported adjustments match
2683     the MTA reported value.
2684 
2685     However, due to issues with layered costing in LIFO/FIFO orgs, the
2686     system inventory value is computed using the cost at the time when
2687     the entry was made. Thus the reported system inventory value
2688     matches the one reported in Oracle Forms.
2689 
2690     We are only interested in entries completed after the global start
2691     date (i.e. entry_status_code = 5 and approval_date > global start date).
2692 
2693     The only MTA rows we are interested in are those that affect the
2694     inventory account (accounting line type = 1).
2695 
2696     MTA does not store rows for expense items, or items in expense
2697     subinventories. Thus the join between MMT and MTA will have to
2698     be an outer join. Rows with no matches will be assigned an
2699     item cost of 0.
2700 
2701     MCCE does not store quantities in the primary uom_code. If the
2702     transaction uom is not the same as the primary uom, all
2703     quantities will have to be converted to the primary uom.
2704 
2705     There is a need to check for adjustment quantity = 0 serial item counts
2706     can have count level matches, but serial number level adjustments,
2707     To handle this, make four enhancements:
2708     1. Declare exact matches if the sum of the MMT primary quantity is 0.
2709     2. Pick the MCCE item_unit_cost if the quantity is 0 (check for expense
2710        subs before that).
2711     3. Set the tolerance to 0 if there is an adjustment in another
2712        subinventory that the one counted. This will automatically
2713        make any adjustments against it misses.
2714     4. The system_inventory_qty for the other subinventory is the negative
2715        of the adjustment quantity, so that the sum of the adjustment
2716        and system quantity is always 0.
2717 
2718     We will only be scanning MMT rows between the transaction ranges
2719     in the log table.
2720 
2721     Also, since the fact table is at a cycle count entry level,
2722     it is impossible for the sum (mmt.primary_quantity) to be 0. Thus
2723     the item_cost formula of sum (value)/sum (quantity) is always
2724     valid and we need not worry about sum (quantity) being 0 or NULL.
2725 
2726     Since the join conditions between MCCE - MMT - MTA is one to many
2727     to many, join MMT/MTA on transaction_id first.
2728 
2729     Also, to handle serial item adjustments where the adjustment
2730     automatically issues an item from a sub to move it to the next,
2731     use the subinventory_code from MMT, not MCCE.
2732 
2733     -------- R12 Changes
2734     1> Subinventory Transfer type of transaction (MMT.transaction_type_id = 5)
2735        is seen in Cycle Count. This case occurs when a LPN is received in
2736        say BULK, and cycle count is done in say CASE for a specific LPN.
2737        This type of transaction has 2 rows in MMT, one for issue transaction
2738        and other for receipt transaction. But the MTA has no rows for receipt
2739        transaction while it has 2 entries differing only in MTA.primary_quantity.
2740        Can be done through Warehouse mobile.
2741 
2742        Currently for such transactions MMT.cycle_count_id is not populated.
2743        Bug # 4392340 has been logged for the same.
2744 
2745     2> Changes to log table and columns.
2746 
2747     ----------------------
2748 
2749 
2750     Do not commit data. Let the wrapper coordinate committing of data.
2751 
2752     Paramters:
2753     IN:
2754         p_global_start_date - DBI global start date
2755 
2756 
2757     History:
2758     Date        Author              Action
2759     01/19/04    Dinkar Gupta        Defined procedure.
2760     02/10/04    Dinkar Gupta        Added group by transaction_id
2761                                     in the mmt/mta join.
2762                                     Used MMT subinventory_code
2763                                     to handle serial item issues.
2764     02/18/04    Dinkar Gupta        Added condition to handle
2765                                     cases where MMT quantity is 0 for
2766                                     serial items.
2767                                     Also added condition to report miss
2768                                     for adjustments against any other
2769                                     sub than the one being counted.
2770     03/10/04    Dinkar Gupta        Used item_cost from MCCE for system
2771                                     inventory value for LIFO/FIFO org
2772                                     issue.
2773 
2774 
2775     06/22/05    Vishal Gupta        Refer to R12 Changes in the above
2776                                     header.
2777 
2778 
2779 */
2780 PROCEDURE extract_discrete_adj_incr (p_global_start_date IN DATE)
2781 IS
2782     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_adjustments_init';
2783     l_stmt_id           NUMBER;
2784 
2785 BEGIN
2786 
2787     -- initialization block
2788     l_stmt_id := 0;
2789 
2790     l_stmt_id := 10;
2791     -- This procedure only inserts all adjustment entry data into the
2792     -- staging table. For an explanation of the logic, please refer to the
2793     -- procedure header.
2794 
2795     -- Join condition justifications
2796     --
2797     -- to MCCC - on org, header and abc_class. The org is redundant,
2798     -- but this should allow use of U1 index on MCCC.
2799     --
2800     -- to MCCI - on header and item. This should allow use of U1 index
2801     -- on MCCI.
2802     --
2803     -- to MCCH - on header. This should allow use of U1 index.
2804     --
2805     -- to MCCE - on entry. This should allow use of U1 index.
2806     --
2807     -- to MSI - on org and item. This should allow use of the U1 index.
2808     --
2809     -- to SUBS - on org and subinventory code
2810     INSERT
2811     INTO opi_dbi_inv_cca_stg (
2812         organization_id,
2813         inventory_item_id,
2814         cycle_count_header_id,
2815         abc_class_id,
2816         subinventory_code,
2817         cycle_count_entry_id,
2818         source,
2819         approval_date,
2820         uom_code,
2821         system_inventory_qty,
2822         positive_adjustment_qty,
2823         negative_adjustment_qty,
2824         item_unit_cost,
2825         item_adj_unit_cost,
2826         hit_miss_pos,
2827         hit_miss_neg,
2828         exact_match)
2829     SELECT
2830         mcce.organization_id,
2831         mcce.inventory_item_id,
2832         mcce.cycle_count_header_id,
2833         to_char (mccc.abc_class_id),
2834         mmt_mta.subinventory_code,
2835         to_char (mcce.cycle_count_entry_id),
2836         C_OPI_SOURCE,
2837         trunc (mcce.approval_date),
2838         msi.primary_uom_code,
2839         decode (mcce.count_uom_current,
2840                 msi.primary_uom_code,
2841                 decode (mmt_mta.subinventory_code,
2842                         mcce.subinventory, mcce.system_quantity_current,
2843                         -1 * sum (mmt_mta.primary_quantity)),
2844                 decode (mmt_mta.subinventory_code,
2845                         mcce.subinventory,
2846                         inv_convert.inv_um_convert
2847                             (mcce.inventory_item_id, C_MMT_PRECISION,
2848                              mcce.system_quantity_current,
2849                              mcce.count_uom_current,
2850                              msi.primary_uom_code, NULL, NULL),
2851                         inv_convert.inv_um_convert
2852                             (mcce.inventory_item_id, C_MMT_PRECISION,
2853                              -1 * sum (mmt_mta.primary_quantity),
2854                              mcce.count_uom_current,
2855                              msi.primary_uom_code, NULL, NULL))),
2856         CASE WHEN sum (mmt_mta.primary_quantity) > 0 THEN
2857                     sum (mmt_mta.primary_quantity)
2858              ELSE   0
2859              END,
2860         CASE WHEN sum (mmt_mta.primary_quantity) < 0 THEN
2861                     -1 * sum (mmt_mta.primary_quantity)
2862              ELSE   0
2863              END,
2864         decode (subs.asset_inventory,
2865                 C_EXPENSE_SUBINVENTORY, 0,
2866                 mcce.item_unit_cost),
2867         decode (sum (mmt_mta.primary_quantity),
2868                 0, decode (subs.asset_inventory,
2869                            C_EXPENSE_SUBINVENTORY, 0,
2870                            mcce.item_unit_cost),
2871                 nvl (sum (mmt_mta.base_transaction_value)/
2872                      sum (mmt_mta.primary_quantity), 0)),
2873         decode (mmt_mta.subinventory_code,
2874                 mcce.subinventory, nvl (mccc.hit_miss_tolerance_positive,
2875                                         mcch.hit_miss_tolerance_positive),
2876                 0),
2877         decode (mmt_mta.subinventory_code,
2878                 mcce.subinventory, nvl (mccc.hit_miss_tolerance_negative,
2879                                         mcch.hit_miss_tolerance_negative),
2880                 0),
2881         decode (sum (mmt_mta.primary_quantity),
2882                 0, C_EXACT_MATCH,
2883                 C_NO_MATCH)
2884       FROM  mtl_cycle_count_entries mcce,
2885             mtl_cycle_count_headers mcch,
2886             mtl_cycle_count_items mcci,
2887             mtl_cycle_count_classes mccc,
2888             mtl_system_items_b msi,
2889             mtl_secondary_inventories subs,
2890             (SELECT
2891                 mmt.organization_id,
2892                 mmt.inventory_item_id,
2893                 mmt.transaction_date,
2894                 mmt.cycle_count_id,
2895                 decode (mmt.transaction_type_id,
2896                         5, decode(sign(nvl(mta.primary_quantity,0)),
2897                                   1, 0,
2898                                   mmt.primary_quantity),
2899                         mmt.primary_quantity)   primary_quantity,
2900                 decode (mmt.transaction_type_id,
2901                         5, decode(sign(nvl(mta.primary_quantity,0)),
2902                                   1, mmt.transfer_subinventory,
2903                                   mmt.subinventory_code),
2904                         mmt.subinventory_code)  subinventory_code,
2905                 sum (mta.base_transaction_value) base_transaction_value
2906               FROM mtl_material_transactions mmt,
2907                    mtl_transaction_accounts mta,
2908                    opi_dbi_conc_prog_run_log log
2909               WHERE log.etl_type = C_ETL_TYPE
2910                 AND log.driving_table_code = C_LOG_MMT_DRV_TBL
2911                 AND log.load_type = C_LOAD_INCR
2912                 AND mmt.organization_id = log.bound_level_entity_id
2913                 AND mmt.transaction_id >= log.from_bound_id
2914                 AND mmt.transaction_id <  log.to_bound_id
2915                 AND mmt.transaction_date > p_global_start_date
2916                 AND mmt.transaction_source_type_id = 9
2917                 AND mmt.transaction_type_id in ( C_MMT_CYCLE_COUNT_ADJ, 5)
2918                 --AND mmt.transaction_type_id = C_MMT_CYCLE_COUNT_ADJ
2919                 AND mmt.transaction_id = mta.transaction_id (+)
2920                 AND nvl (mta.accounting_line_type, C_INVENTORY_ACCOUNT) =
2921                         C_INVENTORY_ACCOUNT
2922               GROUP BY
2923                     mmt.organization_id,
2924                     mmt.inventory_item_id,
2925                     mmt.transaction_date,
2926                     mmt.cycle_count_id,
2927                     decode (mmt.transaction_type_id,
2928                         5, decode(sign(nvl(mta.primary_quantity,0)),
2929                                   1, 0,
2930                                   mmt.primary_quantity),
2931                         mmt.primary_quantity),
2932                     decode (mmt.transaction_type_id,
2933                         5, decode(sign(nvl(mta.primary_quantity,0)),
2934                                   1, mmt.transfer_subinventory,
2935                                   mmt.subinventory_code),
2936                         mmt.subinventory_code),
2937                     mmt.transaction_id) mmt_mta
2938       WHERE mmt_mta.organization_id = msi.organization_id
2939         AND mmt_mta.inventory_item_id = msi.inventory_item_id
2940         AND mmt_mta.cycle_count_id = mcce.cycle_count_entry_id
2941         AND mcce.entry_status_code = C_COMPLETED_CCA_ENTRY
2942         AND mcce.cycle_count_header_id = mcch.cycle_count_header_id
2943         AND mcce.cycle_count_header_id = mcci.cycle_count_header_id
2944         AND mcce.inventory_item_id = mcci.inventory_item_id
2945         AND mcce.organization_id = mccc.organization_id
2946         AND mcce.cycle_count_header_id = mccc.cycle_count_header_id
2947         AND mcci.abc_class_id = mccc.abc_class_id
2948         AND mmt_mta.organization_id = subs.organization_id
2949         AND mmt_mta.subinventory_code = subs.secondary_inventory_name
2950       GROUP BY
2951         mcce.organization_id,
2952         mcce.inventory_item_id,
2953         mcce.cycle_count_header_id,
2954         mccc.abc_class_id,
2955         mmt_mta.subinventory_code,
2956         mcce.cycle_count_entry_id,
2957         trunc (mcce.approval_date),
2958         msi.primary_uom_code,
2959         mcce.count_uom_current,
2960         mcce.system_quantity_current,
2961         subs.asset_inventory,
2962         mcce.item_unit_cost,
2963         mcce.subinventory,
2964         mccc.hit_miss_tolerance_positive,
2965         mcch.hit_miss_tolerance_positive,
2966         mcce.subinventory,
2967         mccc.hit_miss_tolerance_negative,
2968         mcch.hit_miss_tolerance_negative;
2969 
2970     RETURN;
2971 
2972 EXCEPTION
2973 
2974     WHEN OTHERS THEN
2975 
2976         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
2977                                                      l_stmt_id));
2978 
2979         RAISE ADJUSTMENT_EXTR_ERROR;
2980 
2981 END extract_discrete_adj_incr;
2982 
2983 
2984 
2985 /* extract_process_adj_incr
2986 
2987     Extract process adjustment entry data from MTL_CYCLE_COUNT_ENTRIES (MCCE),
2988     MMT and GTV. The transactions in GTV can be either in Draft, New or Final Mode.
2989     We will only consider Draft and Final Mode of transactions only.
2990 
2991     For initial load there will not be any separate bounds for Final and Draft
2992     transaction.
2993 
2994     Subinventory Transafer type of transaction for Cycle Count is considered. There
2995     is no change from discrete.
2996 
2997         1> Subinventory Transfer type of transaction (MMT.transaction_type_id = 5)
2998        is seen in Cycle Count. This case occurs when a LPN is received in
2999        say BULK, and cycle count is done in say CASE for a specific LPN.
3000        This type of transaction has 2 rows in MMT, one for issue transaction
3001        and other for receipt transaction. But the GTV has no rows for receipt
3002        transaction while it has 2 entries differing only in GTV.subinventory_code.
3003        GTV.subinventory_code will have issue subinventory_code for one of two rows in GTV
3004        pertianing to issue transaction in MMT. The other row will have
3005        MMT.transfer_subinventory in GTV.subinventory_code.
3006 
3007 
3008        Currently for such transactions MMT.cycle_count_id is not populated.
3009        Bug # 4392340 has been logged for the same.
3010 
3011     The bounds for Process is applied same for all organization. The driving table
3012     will be GTV.
3013     To isolate cycle count transaction in GTV following is required:
3014     EVENT_CLASS_CODE = 'MISC_TXN' and 'SUBINV_XFER'
3015     EVENT_TYPE_CODE = 'CYCLE_COUNT_ADJ'	and 'CYCLE_COUNT_XFER'
3016     JOURNAL_LINE_TYPE = 'INV'
3017     TRANSACTION_SOURCE = 'INVENTORY'
3018 
3019     We are only interested in entries completed after the global start
3020     date (i.e. entry_status_code = 5 and approval_date > global start date).
3021 
3022     Unlike the case with MTA, GTV has rows for expense items, or items in
3023     expense subinventories. Hence also no outer join is required.
3024 
3025     Adjustments can get costed well after approval and interim cost updates may
3026     cause the values recorded in MCCE to be different. Thus we need to get the
3027     cost associated to the item using the value in GTV so that the reported
3028     adjustments match the GTV reported value.
3029 
3030     However, due to issues with layered costing in LIFO/FIFO orgs, the
3031     system inventory value is computed using the cost at the time when
3032     the entry was made. Thus the reported system inventory value
3033     matches the one reported in Oracle Forms.
3034 
3035     MCCE does not store quantities in the primary uom_code. If the
3036     transaction uom is not the same as the primary uom, all
3037     quantities will have to be converted to the primary uom.
3038 
3039     Also, since the fact table is at a cycle count entry level,
3040     it is impossible for the sum (mmt.primary_quantity) to be 0. Thus
3041     the item_cost formula of sum (value)/sum (quantity) is always
3042     valid and we need not worry about sum (quantity) being 0 or NULL.
3043 
3044     Since the join conditions between MCCE - MMT - GTV is one to many
3045     to many, join GTV/MMT on transaction_id first.
3046 
3047     Do not commit data. Let the wrapper coordinate committing of data.
3048 
3049     Paramters:
3050     IN:
3051         p_global_start_date - DBI global start date
3052 
3053     History:
3054     Date        Author              Action
3055     06/22/05    Vishal Gupta        New Procedure. To collect data for
3056                                     Post R12 Process cycle counting,
3057 
3058 
3059 */
3060 PROCEDURE extract_process_adj_incr (p_global_start_date IN DATE)
3061 IS
3062     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_adjustments_init';
3063     l_stmt_id           NUMBER;
3064     l_from_bound_date   OPI_DBI_CONC_PROG_RUN_LOG.from_bound_date%type;
3065     l_to_bound_date     OPI_DBI_CONC_PROG_RUN_LOG.to_bound_date%type;
3066 
3067 BEGIN
3068 
3069     -- initialization block
3070     l_stmt_id := 0;
3071 
3072     SELECT from_bound_date, to_bound_date
3073     INTO l_from_bound_date, l_to_bound_date
3074     FROM OPI_DBI_CONC_PROG_RUN_LOG
3075     WHERE driving_table_code = C_LOG_GTV_DRV_TBL
3076       AND etl_type = C_ETL_TYPE
3077       AND load_type = C_LOAD_INCR;
3078 
3079 
3080     l_stmt_id := 10;
3081     -- This procedure only inserts all adjustment entry data into the
3082     -- staging table. For an explanation of the logic, please refer to the
3083     -- procedure header.
3084 
3085     -- Join condition justifications
3086     --
3087     -- to MCCC - on org, header and abc_class. The org is redundant,
3088     -- but this should allow use of U1 index on MCCC.
3089     --
3090     -- to MCCI - on header and item. This should allow use of U1 index
3091     -- on MCCI.
3092     --
3093     -- to MCCH - on header. This should allow use of U1 index.
3094     --
3095     -- to MCCE - on entry. This should allow use of U1 index.
3096     --
3097     -- to MSI - on org and item. This should allow use of the U1 index.
3098     --
3099     -- to SUBS - on org and subinventory code
3100 
3101 
3102      INSERT
3103      INTO opi_dbi_inv_cca_stg (
3104         organization_id,
3105         inventory_item_id,
3106         cycle_count_header_id,
3107         abc_class_id,
3108         subinventory_code,
3109         cycle_count_entry_id,
3110         source,
3111         approval_date,
3112         uom_code,
3113         system_inventory_qty,
3114         positive_adjustment_qty,
3115         negative_adjustment_qty,
3116         item_unit_cost,
3117         item_adj_unit_cost,
3118         hit_miss_pos,
3119         hit_miss_neg,
3120         exact_match   )
3121      SELECT  mcce.organization_id,
3122       mcce.inventory_item_id,
3123       mcce.cycle_count_header_id,
3124       to_char (mccc.abc_class_id),
3125       mmt_gtv.subinventory_code,
3126       to_char (mcce.cycle_count_entry_id),
3127       C_OPM_SOURCE,
3128       trunc (mcce.approval_date),
3129       msi.primary_uom_code,
3130       decode (mcce.count_uom_current,
3131       msi.primary_uom_code,
3132       mcce.system_quantity_current,
3133       inv_convert.inv_um_convert (      mcce.inventory_item_id,
3134                                         C_MMT_PRECISION,
3135                                         mcce.system_quantity_current,
3136                                         mcce.count_uom_current,
3137                                         msi.primary_uom_code,
3138                                         NULL,
3139                                         NULL)) system_inventory_qty,
3140       CASE WHEN sum (mmt_gtv.primary_quantity) > 0 THEN
3141                 sum (mmt_gtv.primary_quantity)
3142            ELSE   0
3143       END          positive_adjustment_qty,
3144       CASE WHEN sum (mmt_gtv.primary_quantity) < 0 THEN
3145                 -1 * sum (mmt_gtv.primary_quantity)
3146       ELSE   0
3147       END          negative_adjustment_qty ,
3148       decode (subs.asset_inventory,
3149                 C_EXPENSE_SUBINVENTORY, 0,
3150                 mcce.item_unit_cost)        item_unit_cost,
3151       decode (sum (mmt_gtv.primary_quantity),
3152                 0, decode (subs.asset_inventory,
3153                                 C_EXPENSE_SUBINVENTORY, 0,
3154                                 mcce.item_unit_cost),
3155                 nvl (sum (mmt_gtv.transaction_base_value)/
3156                         sum (mmt_gtv.primary_quantity), 0))        item_adj_unit_cost,
3157       decode (mmt_gtv.subinventory_code,
3158               mcce.subinventory, nvl (mccc.hit_miss_tolerance_positive,
3159                                       mcch.hit_miss_tolerance_positive),
3160               0),
3161       decode (mmt_gtv.subinventory_code,
3162               mcce.subinventory, nvl (mccc.hit_miss_tolerance_negative,
3163                                       mcch.hit_miss_tolerance_negative),
3164               0),
3165       decode (sum (mmt_gtv.primary_quantity),
3166               0, C_EXACT_MATCH,
3167               C_NO_MATCH)          exact_match
3168     FROM    mtl_cycle_count_entries mcce,
3169         mtl_cycle_count_headers mcch,
3170         mtl_cycle_count_items mcci,
3171         mtl_cycle_count_classes mccc,
3172         mtl_system_items_b msi,
3173         mtl_secondary_inventories subs,
3174 	-- as MMT to GTV is one to many relation grouping is done
3175 	-- by transaction_id and primary_quantity level.
3176         (SELECT  mmt.organization_id,
3177                 mmt.transaction_id,
3178                 mmt.inventory_item_id,
3179                 mmt.cycle_count_id,
3180                 DECODE (mmt.transaction_type_id ,
3181                     5 , DECODE(GTV.subinventory_code,
3182                         MMT.subinventory_code, MMT.primary_quantity,
3183                         mmt.transfer_subinventory, -1* MMT.primary_quantity),mmt.primary_quantity)   primary_quantity,
3184                 DECODE (mmt.transaction_type_id ,
3185                     5 ,GTV.subinventory_code,
3186                     mmt.subinventory_code)  subinventory_code,
3187                 SUM (gtv.txn_base_value) transaction_base_value
3188         FROM    mtl_material_transactions mmt ,
3189                 (SELECT gt.*
3190                 FROM gmf_transaction_valuation gt,
3191                 opi_dbi_org_le_temp olt
3192                 WHERE olt.organization_id = gt.organization_id
3193                 AND olt.ledger_id = gt.ledger_id
3194                 AND olt.legal_entity_id = gt.legal_entity_id
3195                 AND olt.valuation_cost_type_id = gt.valuation_cost_type_id) gtv
3196         WHERE   gtv.event_class_code in ( 'MISC_TXN','SUBINV_XFER')
3197          AND    gtv.event_type_code in ('CYCLE_COUNT_ADJ','CYCLE_COUNT_XFER')
3198          AND    gtv.journal_line_type = 'INV'
3199          AND    gtv.transaction_source = 'INVENTORY'
3200          AND    gtv.transaction_date >= l_from_bound_date
3201 	 -- all draft rows are considered in every incremental run
3202          AND    DECODE( accounted_flag,
3203                         NULL, gtv.final_posting_date,
3204                        'D',s_global_start_date) < l_to_bound_date
3205          and    gtv.transaction_id = mmt.transaction_id
3206         GROUP BY
3207                 mmt.organization_id,
3208                 mmt.inventory_item_id,
3209                 mmt.cycle_count_id,
3210                 DECODE (mmt.transaction_type_id ,
3211                     5 , DECODE(GTV.subinventory_code,
3212                         MMT.subinventory_code, MMT.primary_quantity,
3213                         mmt.transfer_subinventory, -1* MMT.primary_quantity),mmt.primary_quantity),
3214                 DECODE (mmt.transaction_type_id ,
3215                     5 ,GTV.subinventory_code,
3216                     mmt.subinventory_code) ,
3217                 mmt.transaction_id) mmt_gtv
3218     WHERE   mmt_gtv.organization_id = msi.organization_id
3219       AND   mmt_gtv.inventory_item_id = msi.inventory_item_id
3220       AND   mmt_gtv.cycle_count_id = mcce.cycle_count_entry_id
3221       AND   mcce.entry_status_code = C_COMPLETED_CCA_ENTRY -- 5
3222       AND   mcce.cycle_count_header_id = mcch.cycle_count_header_id
3223       AND   mcce.cycle_count_header_id = mcci.cycle_count_header_id
3224       AND   mcce.inventory_item_id = mcci.inventory_item_id
3225       AND   mcce.organization_id = mccc.organization_id
3226       AND   mcce.cycle_count_header_id = mccc.cycle_count_header_id
3227       AND   mcci.abc_class_id = mccc.abc_class_id
3228       AND   mmt_gtv.organization_id = subs.organization_id
3229       AND   mmt_gtv.subinventory_code = subs.secondary_inventory_name
3230     GROUP BY
3231             mcce.organization_id,
3232             mcce.inventory_item_id,
3233             mcce.cycle_count_header_id,
3234             mccc.abc_class_id,
3235             mmt_gtv.subinventory_code,
3236             mcce.cycle_count_entry_id,
3237             trunc (mcce.approval_date),
3238             msi.primary_uom_code,
3239             mcce.count_uom_current,
3240             mcce.system_quantity_current,
3241             subs.asset_inventory,
3242             mcce.item_unit_cost,
3243             mcce.subinventory,
3244             mccc.hit_miss_tolerance_positive,
3245             mcch.hit_miss_tolerance_positive,
3246             mcce.subinventory,
3247             mccc.hit_miss_tolerance_negative,
3248             mcch.hit_miss_tolerance_negative;
3249 
3250 
3251 
3252    RETURN;
3253 
3254 EXCEPTION
3255 
3256     WHEN OTHERS THEN
3257 
3258         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
3259                                                      l_stmt_id));
3260 
3261         RAISE ADJUSTMENT_EXTR_ERROR;
3262 
3263 END extract_process_adj_incr;
3264 
3265 
3266 
3267 
3268 /* extract_exact_matches_incr
3269 
3270     Extract the exact match entry data from the MTL_CYCLE_COUNT_ENTRIES
3271     table. Exact match data is easier to handle than adjustment entries
3272     because exact matches are approved on creation and there are no
3273     other transaction tables that need to be visited.
3274 
3275     We are only interested in entries completed after the global start
3276     date (i.e. entry_status_code = 5 and approval_date > global start date).
3277 
3278     The adjustment quantity is always 0 and hit/miss tolerances are not
3279     needed since all entries are, by definition, hits. We still need to join
3280     to MTL_CYCLE_COUNT_CLASSES to get the count and count class information.
3281 
3282     No need to join to MTL_CYCLE_COUNT_HEADERS as we don't need to
3283     get any tolerances.
3284 
3285     MCCE does not store quantities in the primary uom_code. If the
3286     transaction uom is not the same as the primary uom, all
3287     quantities will have to be converted to the primary uom.
3288 
3289     The date range being extracted is specified in the log table.
3290 
3291     However, since we are dealing with last_update_dates, we need to
3292     be sure that the dates in the log tables have timestamps so that
3293     we do not collect partially collected days again.
3294 
3295     The one special case is that we need to identify expense
3296     subinventories and set the item cost to 0 for all entries
3297     bearing those subinventory codes.
3298 
3299 
3300     ------------ R12 Changes
3301     Since Process exact matches will be extracted in the same insert.
3302     Date bounds speific to organization based on first uncosted transaction
3303     cannot be applied. Hence we will use date bounds as that for GTV.
3304     ie Collect all the exact matches between global start date and the initial
3305     program run date.
3306     ------------
3307 
3308     Do not commit data. Let the wrapper coordinate committing of data.
3309 
3310     Parameters:
3311     None.
3312 
3313     History:
3314     Date        Author              Action
3315     01/19/04    Dinkar Gupta        Defined procedure.
3316     02/05/04    Dinkar Gupta        Added logic to join to the from and to
3317                                     transaction dates in the log table.
3318     06/22/05    Vishal Gupta        Refer to R12 Changes in the above header.
3319 
3320 */
3321 
3322 PROCEDURE extract_exact_matches_incr
3323 IS
3324     l_proc_name         CONSTANT VARCHAR2 (40) := 'extract_exact_matches_incr';
3325     l_stmt_id	        NUMBER;
3326     l_from_bound_date   OPI_DBI_CONC_PROG_RUN_LOG.from_bound_date%type;
3327     l_to_bound_date     OPI_DBI_CONC_PROG_RUN_LOG.to_bound_date%type;
3328 
3329 BEGIN
3330 
3331     -- initialization block
3332     l_stmt_id := 0;
3333 
3334     SELECT from_bound_date, to_bound_date
3335     INTO l_from_bound_date, l_to_bound_date
3336     FROM OPI_DBI_CONC_PROG_RUN_LOG
3337     WHERE driving_table_code = C_LOG_GTV_DRV_TBL
3338       AND etl_type = C_ETL_TYPE
3339       AND load_type = C_LOAD_INCR;
3340 
3341 
3342     l_stmt_id := 10;
3343     -- This procedure will extract all all exact match data from MCCE
3344     -- and insert it into the staging table. For SQL logic, please refer
3345     -- to the procedure header
3346 
3347     -- Join condition justifications
3348     --
3349     -- to MCCC - on org, header and abc_class. The org is redundant,
3350     -- but this should allow use of U1 index on MCCC.
3351     -- Note the explicit check for the 0 adjustment quantity. This should
3352     -- ideally not be required but we found an example (which we have not
3353     -- been able to recreate) where there was an adjustment on a serialized
3354     -- item but the adjustment date was null in MCCE and
3355     -- MTL_CC_SERIAL_NUMBERS. To filter that case, we filter explicitly on
3356     -- on the quantity. Most likely, this is an OLTP bug that will be
3357     -- fixed.
3358     --
3359     -- to MCCI - on header and item. This should allow use of U1 index
3360     -- on MCCI.
3361     --
3362     -- to MCCE - on entry. This should allow use of U1 index.
3363     --  On entry_status_code. This is the leading column of the N6 index.
3364     --  Filter on last_update_date. This should use the newly created
3365     --  N8 (?) index.
3366     --
3367     -- no join needed to log - as we can extract GTV date bounds into variables
3368     -- .
3369 
3370 
3371     INSERT
3372     INTO opi_dbi_inv_cca_stg (
3373         organization_id,
3374         inventory_item_id,
3375         cycle_count_header_id,
3376         abc_class_id,
3377         subinventory_code,
3378         cycle_count_entry_id,
3379         source,
3380         approval_date,
3381         uom_code,
3382         system_inventory_qty,
3383         positive_adjustment_qty,
3384         negative_adjustment_qty,
3385         item_unit_cost,
3386         item_adj_unit_cost,
3387         hit_miss_pos,
3388         hit_miss_neg,
3389         exact_match)
3390     SELECT
3391         mcce.organization_id,
3392         mcce.inventory_item_id,
3393         mcce.cycle_count_header_id,
3394         to_char (mccc.abc_class_id),
3395         mcce.subinventory,
3396         to_char (mcce.cycle_count_entry_id),
3397         decode(mp.process_enabled_flag,
3398                 'Y',C_OPM_SOURCE,
3399                 C_OPI_SOURCE )  source,
3400         trunc (mcce.approval_date),
3401         msi.primary_uom_code,
3402         decode (mcce.count_uom_current,
3403                 msi.primary_uom_code, mcce.system_quantity_current,
3404                 inv_convert.inv_um_convert
3405                     (mcce.inventory_item_id, C_MMT_PRECISION,
3406                      mcce.system_quantity_current, mcce.count_uom_current,
3407                      msi.primary_uom_code, NULL, NULL)),
3408         0,
3409         0,
3410         decode (subs.asset_inventory,
3411                 C_EXPENSE_SUBINVENTORY, 0,
3412                 mcce.item_unit_cost),
3413         0,
3414         NULL,
3415         NULL,
3416         C_EXACT_MATCH
3417       FROM  mtl_cycle_count_entries mcce,
3418             mtl_cycle_count_items mcci,
3419             mtl_cycle_count_classes mccc,
3420             mtl_system_items_b msi,
3421             mtl_secondary_inventories subs,
3422             mtl_parameters mp
3423       WHERE mcce.last_update_date >= l_from_bound_date
3424         AND mcce.last_update_date < l_to_bound_date
3425         AND mcce.organization_id = mp.organization_id
3426         AND mcce.entry_status_code = C_COMPLETED_CCA_ENTRY  -- 5
3427         AND mcce.adjustment_date IS NULL
3428         AND mcce.adjustment_quantity = 0
3429         AND mcce.cycle_count_header_id = mcci.cycle_count_header_id
3430         AND mcce.inventory_item_id = mcci.inventory_item_id
3431         AND mcce.organization_id = mccc.organization_id
3432         AND mcce.cycle_count_header_id = mccc.cycle_count_header_id
3433         AND mcci.abc_class_id = mccc.abc_class_id
3434         AND mcce.organization_id = msi.organization_id
3435         AND mcce.inventory_item_id = msi.inventory_item_id
3436         AND mcce.organization_id = subs.organization_id
3437         AND mcce.subinventory = subs.secondary_inventory_name;
3438 
3439 
3440         -- Do not commit here. Let the wrapper handle commit operations.
3441 
3442         RETURN;
3443 
3444 EXCEPTION
3445 
3446     WHEN OTHERS THEN
3447 
3448         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
3449                                                      l_stmt_id));
3450 
3451         RAISE EXACT_MATCH_EXTR_ERROR;
3452 
3453 END extract_exact_matches_incr;
3454 
3455 
3456 /*  compute_cca_conv_rates_incr
3457 
3458     Compute all the conversion rates for all distinct organization,
3459     transaction date pairs in the staging table. The date in the fact
3460     table is already without a timestamp i.e. trunc'ed.
3461 
3462     There are two conversion rates to be computed:
3463     1. Primary global
3464     2. Secondary global (if set up)
3465 
3466     The conversion rate work table was truncated during
3467     the initialization phase.
3468 
3469     Get the currency conversion rates based on the data in
3470     OPI_DBI_INV_CCA_STG using the fii_currency.get_global_rate_primary
3471     API for the primary global currency and
3472     fii_currency.get_global_rate_secondary for the secondary global currency.
3473     The primary currency API:
3474     1. finds the conversion rate if one exists.
3475     2. 'USD' always has a conversion rate of 1 (since it is global currency).
3476     3. returns -1 if there is no conversion rate on that date.
3477     4. returns -2 if the currency code is not found.
3478     5. returns -3 if the transaction_date is prior to 01-JAN-1999,
3479        the functional currency code is EUR and there is no EUR to USD
3480        conversion rate defined on 01-JAN-1999.
3481 
3482     The secondary currency API:
3483     1. Finds the global secondary currency rate if one exists.
3484     2. Returns a rate of 1 if the secondary currency has not been set up.
3485     3. Returns -1, -2, -3 in the same way as the primary currency code API.
3486 
3487     If the global and secondary currency codes and rate types are identical,
3488     do not call the secondary currency API. Instead update the secondary
3489     rates from the primary.
3490 
3491     If the secondary currency has not been set up, set the conversion rate
3492     to null.
3493 
3494     If any primary conversion rates are missing, throw an exception.
3495     If any secondary currency rates are missing (after the secondary
3496     currency has been set up) throw an exception.
3497 
3498     Need to commit data here due to insert+append.
3499 
3500     History:
3501     Date        Author              Action
3502     01/15/04    Dinkar Gupta        Defined procedure.
3503     05/11/04    Dinkar Gupta        Specializing this procedure for incr.
3504                                     load.
3505     08/16/04    Dinkar Gupta        Added secondary currency support.
3506 */
3507 
3508 PROCEDURE compute_cca_conv_rates_incr (p_global_curr_code IN VARCHAR2,
3509                                        p_global_rate_type IN VARCHAR2)
3510 
3511 IS
3512 
3513     l_proc_name CONSTANT VARCHAR2 (60) := 'compute_cca_conv_rates_incr';
3514     l_stmt_id NUMBER;
3515 
3516     -- Cursor to see if any rates are missing. See below for details
3517     CURSOR invalid_rates_exist_csr IS
3518         SELECT 1
3519           FROM opi_dbi_inv_cca_conv
3520           WHERE (   nvl (conversion_rate, -999) < 0
3521                  OR nvl (sec_conversion_rate, 999) < 0)
3522             AND rownum < 2;
3523 
3524     invalid_rates_exist_rec invalid_rates_exist_csr%ROWTYPE;
3525 
3526     -- Set up a cursor to get all the invalid rates.
3527     -- By the logic of the fii_currency.get_global_rate_primary
3528     -- and fii_currency.get_global_rate_secondary APIs, the returned value
3529     -- is -ve if no rate exists:
3530     -- -1 for dates with no rate.
3531     -- -2 for unrecognized conversion rates.
3532     -- -3 for missing EUR to USD rates on 01-JAN-1999 when the
3533     --    transaction_date is prior to 01-JAN-1999 (when the EUR
3534     --    officially went into circulation).
3535     --
3536     -- However, with the secondary currency, the null rate means it
3537     -- has not been setup and should therefore not be reported as an
3538     -- error.
3539     --
3540     -- Also, cross check with the org-date pairs in the staging table,
3541     -- in case some orgs never had a functional currency code defined.
3542     CURSOR invalid_rates_csr (p_pri_sec_curr_same NUMBER) IS
3543         SELECT DISTINCT
3544             report_order,
3545             curr_code,
3546             rate_type,
3547             approval_date,
3548             func_currency_code
3549           FROM (
3550                 SELECT DISTINCT
3551                     s_global_curr_code curr_code,
3552                     s_global_rate_type rate_type,
3553                     1 report_order, -- ordering global currency first
3554                     mp.organization_code,
3555                     decode (conv.conversion_rate,
3556                             C_EURO_MISSING_AT_START, C_EURO_START_DATE,
3557                             conv.approval_date) approval_date,
3558                     conv.func_currency_code
3559               FROM opi_dbi_inv_cca_conv conv,
3560                    mtl_parameters mp,
3561                   (SELECT
3562                    DISTINCT organization_id, approval_date
3563                      FROM opi_dbi_inv_cca_stg) to_conv
3564               WHERE nvl (conv.conversion_rate, -999) < 0 -- null is not fine
3565                 AND mp.organization_id = to_conv.organization_id
3566                 AND conv.approval_date (+) = to_conv.approval_date
3567                 AND conv.organization_id (+) = to_conv.organization_id
3568             UNION ALL
3569             SELECT DISTINCT
3570                     s_secondary_curr_code curr_code,
3571                     s_secondary_rate_type rate_type,
3572                     decode (p_pri_sec_curr_same,
3573                             1, 1,
3574                             2) report_order, --ordering secondary currency next
3575                     mp.organization_code,
3576                     decode (conv.sec_conversion_rate,
3577                             C_EURO_MISSING_AT_START, C_EURO_START_DATE,
3578                             conv.approval_date) approval_date,
3579                     conv.func_currency_code
3580               FROM opi_dbi_inv_cca_conv conv,
3581                    mtl_parameters mp,
3582                   (SELECT
3583                    DISTINCT organization_id, approval_date
3584                      FROM opi_dbi_inv_cca_stg) to_conv
3585               WHERE nvl (conv.sec_conversion_rate, 999) < 0 -- null is fine
3586                 AND mp.organization_id = to_conv.organization_id
3587                 AND conv.approval_date (+) = to_conv.approval_date
3588                 AND conv.organization_id (+) = to_conv.organization_id)
3589           ORDER BY
3590                 report_order ASC,
3591                 approval_date,
3592                 func_currency_code;
3593 
3594 
3595     -- Boolean to ensure all rates have been found.
3596     l_all_rates_found BOOLEAN;
3597 
3598     -- Boolean to check if the primary and secondary currencies are the
3599     -- same
3600     l_pri_sec_curr_same NUMBER;
3601 
3602 BEGIN
3603 
3604     -- initialization block
3605     l_stmt_id := 0;
3606     l_all_rates_found := true;
3607     l_pri_sec_curr_same := 0;
3608 
3609     l_stmt_id := 5;
3610     -- check if the primary and secondary currencies and rate types are
3611     -- identical.
3612     IF (s_global_curr_code = nvl (s_secondary_curr_code, '---') AND
3613         s_global_rate_type = nvl (s_secondary_rate_type, '---') ) THEN
3614         l_pri_sec_curr_same := 1;
3615     END IF;
3616 
3617 
3618     l_stmt_id := 10;
3619     -- Get all the distinct organization and date pairs and the
3620     -- base currency codes for the orgs into the conversion rates
3621     -- work table.
3622 
3623     -- Use the fii_currency.get_global_rate_primary function to get the
3624     -- conversion rate given a currency code and a date.
3625     -- The function returns:
3626     -- 1 for currency code of 'USD' which is the global currency
3627     -- -1 for dates for which there is no currency conversion rate
3628     -- -2 for unrecognized currency conversion rates
3629     -- -3 for missing EUR to USD rates on 01-JAN-1999 when the
3630     --    transaction_date is prior to 01-JAN-1999 (when the EUR
3631     --    officially went into circulation).
3632 
3633     -- Use the fii_currency.get_global_rate_secondary to get the secondary
3634     -- global rate. If the secondary currency has not been set up,
3635     -- make the rate null. If the secondary currency/rate types are the
3636     -- same as the primary, don't call the API but rather use an update
3637     -- statement followed by the insert.
3638 
3639     -- By selecting distinct org and currency code from the gl_set_of_books
3640     -- and hr_organization_information, take care of duplicate codes.
3641 
3642     INSERT /*+ append */
3643     INTO opi_dbi_inv_cca_conv (
3644         organization_id,
3645         func_currency_code,
3646         approval_date,
3647         conversion_rate,
3648         sec_conversion_rate)
3649     SELECT
3650         to_conv.organization_id,
3651         curr_codes.currency_code,
3652         to_conv.approval_date,
3653         decode (curr_codes.currency_code,
3654                 s_global_curr_code, 1,
3655                 fii_currency.get_global_rate_primary (
3656                                     curr_codes.currency_code,
3657                                     to_conv.approval_date) ),
3658         decode (s_secondary_curr_code,
3659                 NULL, NULL,
3660                 curr_codes.currency_code, 1,
3661                 decode (l_pri_sec_curr_same,
3662                         1, C_PRI_SEC_CURR_SAME_MARKER,
3663                         fii_currency.get_global_rate_secondary (
3664                             curr_codes.currency_code,
3665                             to_conv.approval_date)))
3666       FROM
3667         (SELECT
3668          DISTINCT organization_id, approval_date
3669            FROM opi_dbi_inv_cca_stg) to_conv,
3670         (SELECT
3671          DISTINCT hoi.organization_id, gsob.currency_code
3672            FROM hr_organization_information hoi,
3673                 gl_sets_of_books gsob
3674            WHERE hoi.org_information_context  = 'Accounting Information'
3675              AND hoi.org_information1  = to_char(gsob.set_of_books_id))
3676         curr_codes
3677       WHERE curr_codes.organization_id  = to_conv.organization_id;
3678 
3679     l_stmt_id := 15;
3680     commit;   -- due to insert+append
3681 
3682     l_stmt_id := 20;
3683     -- if the primary and secondary currency codes are the same, then
3684     -- update the secondary with the primary
3685     IF (l_pri_sec_curr_same = 1) THEN
3686 
3687         l_stmt_id := 30;
3688         UPDATE /*+ parallel (opi_dbi_inv_cca_conv) */ opi_dbi_inv_cca_conv
3689         SET sec_conversion_rate = conversion_rate;
3690 
3691         -- safe to commit, as before
3692         l_stmt_id := 40;
3693         commit;
3694 
3695     END IF;
3696 
3697     -- Check that all rates have been found and are non-negative.
3698     -- If there is a problem, notify user.
3699     l_stmt_id := 50;
3700     OPEN invalid_rates_exist_csr;
3701     FETCH invalid_rates_exist_csr INTO invalid_rates_exist_rec;
3702     IF (invalid_rates_exist_csr%FOUND) THEN
3703 
3704         -- print the header out
3705         BIS_COLLECTION_UTILITIES.writeMissingRateHeader;
3706 
3707         -- all rates not found
3708         l_all_rates_found := false;
3709 
3710         FOR invalid_rate_rec IN invalid_rates_csr (l_pri_sec_curr_same)
3711         LOOP
3712 
3713             BIS_COLLECTION_UTILITIES.writeMissingRate(
3714                invalid_rate_rec.rate_type,
3715                invalid_rate_rec.func_currency_code,
3716                invalid_rate_rec.curr_code,
3717                invalid_rate_rec.approval_date);
3718 
3719         END LOOP;
3720     END IF;
3721 
3722     l_stmt_id := 55;
3723     CLOSE invalid_rates_exist_csr;
3724 
3725     -- If all rates not found raise an exception
3726     l_stmt_id := 60;
3727     IF (l_all_rates_found = FALSE) THEN
3728         RAISE MISSING_CONV_RATES;
3729     END IF;
3730 
3731     RETURN;
3732 
3733 EXCEPTION
3734 
3735     WHEN MISSING_CONV_RATES THEN
3736 
3737         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg
3738                                             (MISSING_CONV_RATES_MESG,
3739                                              l_proc_name, l_stmt_id));
3740         RAISE CONV_RATES_ERROR;
3741 
3742 
3743     WHEN OTHERS THEN
3744 
3745         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
3746                                                      l_stmt_id));
3747 
3748         RAISE CONV_RATES_ERROR;
3749 
3750 
3751 END compute_cca_conv_rates_incr;
3752 
3753 
3754 /* populate_fact_incr
3755 
3756     Move all the staging table data into the fact table. The granularity
3757     of the data remains the same as the staging table i.e. the
3758     cycle count entry level.
3759 
3760     The fact joins to the conversion rates table to compute the values
3761     in both the functional currency and global currency.
3762 
3763     Quantities in the staging table are already the primary UOM.
3764 
3765     Adjustment values are computed using the item_adj_unit_cost which
3766     is derived from the MTA base_transaction_value. Thus reported
3767     adjustment values always match MTA.
3768 
3769     System inventory values are computed using the item_unit_cost which
3770     is the cost of the item at the time when the entry was first entered.
3771     Thus system inventory value matches that reported in Oracle Forms.
3772     This is to work around the issues of layered costing in LIFO/FIFO
3773     orgs (bug 3471888).
3774 
3775     Use the absolute value of system quantity to compute hit/miss because
3776     the system quantity can be negative. The tolerances however are
3777     defined as positive numbers. The sign and value of the adjustment
3778     are otherwise correct to allow for using absolute value of
3779     system quantity.
3780 
3781     The computation of whether an entry is a hit or a miss is done in
3782     this step.
3783     1. If the entry is an exact match, it is a hit.
3784     2. If the +ve and -ve hit/miss tolerances are null, it is a hit.
3785     3. If the adjustment is +ve:
3786         - if the +ve tolerance is null, it is a hit.
3787         - else (adjustment_qty/system_inventory_qty) <=
3788             (+ve tolerance)/100, it is a hit.
3789     4. If the adjustment is +ve:
3790         - if the +ve tolerance is null, it is a hit.
3791         - else (adjustment_qty/system_inventory_qty) <=
3792             (+ve tolerance)/100, it is a hit.
3793         This check handles the divide by 0 case.
3794     5. If the adjustment is -ve:
3795         - if the -ve tolerance is null, it is a hit.
3796         - else (adjustment_qty/system_inventory_qty) <=
3797             (-ve tolerance)/100, it is a hit. [since both the negative
3798             adjustment quantities and tolerances are reported as
3799             positive numbers.]
3800     6. Any other case is a miss.
3801 
3802     The only thing to be careful of in this step is the condition on the
3803     merge. In case the merge condition needs to insert, there is no
3804     complication. Insert as in the initial load.
3805     In case the merge condition needs to update, the type of entry matters.
3806     For exact matches, the entry can be simply updated.
3807     For adjustments, the entry needs to be appended because of the case
3808     where serial adjustments can create multiple MMT transactions. In that
3809     case, it is possible for one of the transactions to be uncosted. In
3810     next run, these will get picked up and need to be appended to the
3811     previous values. The hit/miss calculations will have to be done
3812     based on the new appended values too.
3813 
3814     Do not commit anything in this step. Let the wrapper handle that.
3815 
3816     History:
3817     Date        Author              Action
3818     01/19/04    Dinkar Gupta        Defined procedure.
3819     02/09/04    Dinkar Gupta        Used absolute value of
3820                                     system inventory quantity
3821                                     to compute hit/miss.
3822     03/10/04    Dinkar Gupta        Used item_cost from MCCE for system
3823                                     inventory value and cost from MTA
3824                                     for adjustment value to account for
3825                                     for LIFO/FIFO org layered costing.
3826     08/17/04    Dinkar Gupta        Added secondary currency support
3827 */
3828 
3829 PROCEDURE populate_fact_incr
3830 IS
3831 
3832     l_proc_name CONSTANT VARCHAR2(40) := 'populate_fact_incr';
3833     l_stmt_id NUMBER;
3834 
3835 BEGIN
3836 
3837     -- initialization block
3838     l_stmt_id := 0;
3839 
3840     l_stmt_id := 10;
3841     -- Merge data into the fact table. For an explanation of the logic
3842     -- see the procedure header.
3843     MERGE INTO opi_dbi_inv_cca_f base
3844     USING
3845     (SELECT
3846         stg.organization_id,
3847         stg.inventory_item_id,
3848         stg.cycle_count_header_id,
3849         stg.abc_class_id,
3850         stg.subinventory_code,
3851         stg.cycle_count_entry_id,
3852         stg.source,
3853         stg.approval_date,
3854         stg.uom_code,
3855         stg.system_inventory_qty,
3856         (stg.system_inventory_qty * stg.item_unit_cost)
3857             system_inventory_val_b,
3858         (stg.system_inventory_qty * stg.item_unit_cost *
3859             conv.conversion_rate) system_inventory_val_g,
3860         (stg.system_inventory_qty * stg.item_unit_cost *
3861             conv.sec_conversion_rate) system_inventory_val_sg,
3862         stg.positive_adjustment_qty,
3863         (stg.positive_adjustment_qty * stg.item_adj_unit_cost)
3864             positive_adjustment_val_b,
3865         (stg.positive_adjustment_qty * stg.item_adj_unit_cost *
3866             conv.conversion_rate) positive_adjustment_val_g,
3867         (stg.positive_adjustment_qty * stg.item_adj_unit_cost *
3868             conv.sec_conversion_rate) positive_adjustment_val_sg,
3869         stg.negative_adjustment_qty,
3870         (stg.negative_adjustment_qty * stg.item_adj_unit_cost)
3871             negative_adjustment_val_b,
3872         (stg.negative_adjustment_qty * stg.item_adj_unit_cost *
3873             conv.conversion_rate) negative_adjustment_val_g,
3874         (stg.negative_adjustment_qty * stg.item_adj_unit_cost *
3875             conv.sec_conversion_rate) negative_adjustment_val_sg,
3876         conv.conversion_rate,
3877         conv.sec_conversion_rate,
3878         stg.item_unit_cost,
3879         CASE
3880             WHEN stg.exact_match = C_EXACT_MATCH THEN
3881                 C_HIT
3882             WHEN stg.hit_miss_pos IS NULL AND stg.hit_miss_neg IS NULL THEN
3883                 C_HIT
3884             WHEN stg.hit_miss_pos IS NULL AND
3885                  stg.positive_adjustment_qty > 0 THEN
3886                 C_HIT
3887             WHEN stg.hit_miss_neg IS NULL AND
3888                  stg.negative_adjustment_qty > 0 THEN
3889                 C_HIT
3890             WHEN stg.system_inventory_qty = 0 THEN
3891                 CASE
3892                     WHEN stg.positive_adjustment_qty = 0 AND
3893                          stg.negative_adjustment_qty = 0 THEN
3894                         C_HIT
3895                     ELSE
3896                         C_MISS
3897                 END
3898             WHEN stg.positive_adjustment_qty > 0 AND
3899                  (stg.positive_adjustment_qty/
3900                   abs (stg.system_inventory_qty)) <=
3901                  (stg.hit_miss_pos/100) THEN
3902                 C_HIT
3903             WHEN stg.negative_adjustment_qty > 0 AND
3904                  (stg.negative_adjustment_qty/
3905                   abs (stg.system_inventory_qty)) <=
3906                  (stg.hit_miss_neg/100) THEN
3907                 C_HIT
3908             ELSE
3909                 C_MISS
3910             END hit_or_miss,
3911         stg.exact_match,
3912         stg.hit_miss_pos,
3913         stg.hit_miss_neg,
3914         sysdate last_update_date,
3915         s_user_id last_updated_by,
3916         s_login_id last_update_login,
3917         sysdate creation_date,
3918         s_user_id created_by,
3919         s_request_id request_id,
3920         s_program_application_id program_application_id,
3921         s_program_id program_id,
3922         sysdate program_update_date
3923       FROM  opi_dbi_inv_cca_stg stg,
3924             opi_dbi_inv_cca_conv conv
3925       WHERE stg.organization_id = conv.organization_id
3926         AND stg.approval_date = conv.approval_date) new
3927     ON (
3928             base.cycle_count_entry_id = new.cycle_count_entry_id
3929         AND base.subinventory_code = new.subinventory_code
3930         AND base.source = new.source)
3931     WHEN MATCHED THEN UPDATE
3932     SET
3933         system_inventory_qty = new.system_inventory_qty,
3934         system_inventory_val_b = new.system_inventory_val_b,
3935         system_inventory_val_g = new.system_inventory_val_g,
3936         system_inventory_val_sg = new.system_inventory_val_sg,
3937         positive_adjustment_qty =
3938             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3939                       new.source = C_OPM_SOURCE THEN
3940                     new.positive_adjustment_qty
3941                  ELSE new.positive_adjustment_qty +
3942                       base.positive_adjustment_qty
3943             END,
3944         positive_adjustment_val_b =
3945             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3946                       new.source = C_OPM_SOURCE THEN
3947                     new.positive_adjustment_val_b
3948                  ELSE new.positive_adjustment_val_b +
3949                       base.positive_adjustment_val_b
3950             END,
3951         positive_adjustment_val_g =
3952             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3953                       new.source = C_OPM_SOURCE THEN
3954                     new.positive_adjustment_val_g
3955                  ELSE new.positive_adjustment_val_g +
3956                       base.positive_adjustment_val_g
3957             END,
3958         positive_adjustment_val_sg =
3959             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3960                       new.source = C_OPM_SOURCE THEN
3961                     new.positive_adjustment_val_sg
3962                  ELSE new.positive_adjustment_val_sg +
3963                       base.positive_adjustment_val_sg
3964             END,
3965         negative_adjustment_qty =
3966             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3967                       new.source = C_OPM_SOURCE THEN
3968                     new.negative_adjustment_qty
3969                  ELSE new.negative_adjustment_qty +
3970                       base.negative_adjustment_qty
3971             END,
3972         negative_adjustment_val_b =
3973             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3974                       new.source = C_OPM_SOURCE THEN
3975                     new.negative_adjustment_val_b
3976                  ELSE new.negative_adjustment_val_b +
3977                       base.negative_adjustment_val_b
3978             END,
3979         negative_adjustment_val_g =
3980             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3981                       new.source = C_OPM_SOURCE THEN
3982                     new.negative_adjustment_val_g
3983                  ELSE new.negative_adjustment_val_g +
3984                       base.negative_adjustment_val_g
3985             END,
3986         negative_adjustment_val_sg =
3987             CASE WHEN new.exact_match = C_EXACT_MATCH OR
3988                       new.source = C_OPM_SOURCE THEN
3989                     new.negative_adjustment_val_sg
3990                  ELSE new.negative_adjustment_val_sg +
3991                       base.negative_adjustment_val_sg
3992             END,
3993         hit_or_miss =
3994         CASE
3995             WHEN new.source = C_OPM_SOURCE THEN
3996                 new.hit_or_miss
3997             WHEN new.exact_match = C_EXACT_MATCH THEN
3998                 C_HIT
3999             WHEN new.hit_miss_pos IS NULL AND new.hit_miss_neg IS NULL THEN
4000                 C_HIT
4001             WHEN new.source = C_OPI_SOURCE THEN
4002                 CASE
4003                     WHEN new.hit_miss_pos IS NULL AND
4004                          base.positive_adjustment_qty +
4005                          new.positive_adjustment_qty > 0 THEN
4006                         C_HIT
4007                     WHEN new.hit_miss_neg IS NULL AND
4008                          base.negative_adjustment_qty +
4009                          new.negative_adjustment_qty > 0 THEN
4010                         C_HIT
4011                     WHEN new.system_inventory_qty +
4012                          base.system_inventory_qty = 0 THEN
4013                         CASE
4014                             WHEN new.positive_adjustment_qty +
4015                                  base.positive_adjustment_qty = 0 AND
4016                                  new.negative_adjustment_qty +
4017                                  base.negative_adjustment_qty = 0 THEN
4018                                 C_HIT
4019                             ELSE
4020                                 C_MISS
4021                         END
4022                     WHEN new.positive_adjustment_qty > 0 AND
4023                          ((new.positive_adjustment_qty +
4024                            base.positive_adjustment_qty)/
4025                            abs (new.system_inventory_qty)) <=
4026                          (new.hit_miss_pos/100) THEN
4027                         C_HIT
4028                     WHEN new.negative_adjustment_qty > 0 AND
4029                          ((new.negative_adjustment_qty +
4030                            base.negative_adjustment_qty)/
4031                            abs (new.system_inventory_qty)) <=
4032                          (new.hit_miss_neg/100) THEN
4033                         C_HIT
4034                     ELSE
4035                         C_MISS
4036                 END
4037             ELSE
4038                 C_MISS  -- should never get here!!
4039         END,
4040         exact_match = new.exact_match,
4041         last_update_date = new.last_update_date,
4042         last_updated_by = new.last_updated_by,
4043         last_update_login = new.last_update_login,
4044         creation_date = new.creation_date,
4045         created_by = new.created_by,
4046         request_id = new.request_id,
4047         program_application_id = new.program_application_id,
4048         program_id = new.program_id,
4049         program_update_date = new.program_update_date
4050     WHEN NOT MATCHED THEN INSERT (
4051         organization_id,
4052         inventory_item_id,
4053         cycle_count_header_id,
4054         abc_class_id,
4055         subinventory_code,
4056         cycle_count_entry_id,
4057         source,
4058         approval_date,
4059         uom_code,
4060         system_inventory_qty,
4061         system_inventory_val_b,
4062         system_inventory_val_g,
4063         system_inventory_val_sg,
4064         positive_adjustment_qty,
4065         positive_adjustment_val_b,
4066         positive_adjustment_val_g,
4067         positive_adjustment_val_sg,
4068         negative_adjustment_qty,
4069         negative_adjustment_val_b,
4070         negative_adjustment_val_g,
4071         negative_adjustment_val_sg,
4072         conversion_rate,
4073         sec_conversion_rate,
4074         item_unit_cost,
4075         hit_or_miss,
4076         exact_match,
4077         last_update_date,
4078         last_updated_by,
4079         last_update_login,
4080         creation_date,
4081         created_by,
4082         request_id,
4083         program_application_id,
4084         program_id,
4085         program_update_date)
4086     VALUES (
4087         new.organization_id,
4088         new.inventory_item_id,
4089         new.cycle_count_header_id,
4090         new.abc_class_id,
4091         new.subinventory_code,
4092         new.cycle_count_entry_id,
4093         new.source,
4094         new.approval_date,
4095         new.uom_code,
4096         new.system_inventory_qty,
4097         new.system_inventory_val_b,
4098         new.system_inventory_val_g,
4099         new.system_inventory_val_sg,
4100         new.positive_adjustment_qty,
4101         new.positive_adjustment_val_b,
4102         new.positive_adjustment_val_g,
4103         new.positive_adjustment_val_sg,
4104         new.negative_adjustment_qty,
4105         new.negative_adjustment_val_b,
4106         new.negative_adjustment_val_g,
4107         new.negative_adjustment_val_sg,
4108         new.conversion_rate,
4109         new.sec_conversion_rate,
4110         new.item_unit_cost,
4111         new.hit_or_miss,
4112         new.exact_match,
4113         new.last_update_date,
4114         new.last_updated_by,
4115         new.last_update_login,
4116         new.creation_date,
4117         new.created_by,
4118         new.request_id,
4119         new.program_application_id,
4120         new.program_id,
4121         new.program_update_date);
4122 
4123 
4124     -- Do not commit here. Let the wrapper handle that.
4125 
4126     RETURN;
4127 
4128 EXCEPTION
4129 
4130     WHEN OTHERS THEN
4131 
4132         BIS_COLLECTION_UTILITIES.PUT_LINE (err_mesg (SQLERRM, l_proc_name,
4133                                                      l_stmt_id));
4134 
4135         RAISE FACT_MERGE_ERROR;
4136 
4137 END populate_fact_incr;
4138 
4139 
4140 END opi_dbi_inv_cca_pkg;