Tuesday, March 18, 2014

How to Query the Service Contracts Tables for Header, Line, Subline and Billing Information (11.5.10+ ) - 467334.1

A. Contract Header Data

This SQL takes data from views rather than from actual contracts tables and is useful for reviewing data but not ideal for verifying if base tables hold correct data.


SELECT contract_number "Contract"
     , TO_CHAR( id ) "Id"
     , short_description "Description"
     , inv_organization_id "Organization Id"
     , sts_code "Status"
     , scs_code
     , currency_code "Currency"
     , TO_CHAR( date_terminated
              , 'DD-MON-YYYY' )
          "Date Terminated"
     , trn_code
     , TO_CHAR( start_date
              , 'DD-MON-YYYY' )
          "Start Date"
     , TO_CHAR( end_date
              , 'DD-MON-YYYY' )
          " End Date"
     , upg_orig_system_ref
     , price_list_id
     , bill_to_site_use_id
     , ship_to_site_use_id
     , payment_term_id
     , acct_rule_id
     , inv_rule_id
     , ar_interface_yn
     , class_meaning
     , template_yn
     , hold_billing
  FROM oks_auth_headers_v
 WHERE contract_number = :p_contract_number;

SELECT *
  FROM okc_k_headers_b
 WHERE contract_number = :p_contract_number
   AND contract_number_modifier = :p_contract_modifier;

B. Contract Line Data 

Note: in OKC_K_LINES_B the chr_id field is only populated with the contract header id for contract lines.  For contract sublines, this value is NULL.  Dnz_chr_id is populated with the contract header id for both lines and sublines.

B1. This SQL takes data from views rather than from actual contracts tables and is useful for reviewing data but not ideal for verifying if base tables hold correct data 

  SELECT DISTINCT oal.line_number
                , oll.lse_name
                , oal.sts_code "Status"
                , oal.trn_code
                , oal.lse_id
                , old.service_name
                , oal.currency_code "Currency|Code"
                , TO_CHAR( oal.start_date
                         , 'DD-MON-YYYY' )
                     "Start Date"
                , TO_CHAR( oal.end_date
                         , 'DD-MON-YYYY' )
                     "End Date"
                , qpl.name "Price List Name"
                , cust_acct_id
                , bill_to_site_use_id
                , inv_rule_id
                , ship_to_site_use_id
                , ship_to_site_use_id
                , acct_rule_id
                , usage_period
                , usage_type
                , uom_quantified
                , billing_schedule_type
                , invoice_text
    FROM oks_auth_lines_v oal
       , okc_launch_lgrid_v oll
       , qp_pricelists_lov_v qpl
       , oks_line_details_v old
   WHERE oal.id = oll.id
     AND cle_id IS NULL
     AND qpl.price_list_id = oal.price_list_id
     AND old.contract_id = oll.chr_id
     AND oll.chr_id = '<value of id taken from query A1>'
ORDER BY TO_NUMBER line_number ;
***********************************************************
B2. Data taken directly from contract table.  (Note that this query may appear to return duplicate lines, as the query on okc_k_headers_b will return more than one contract if the contract has been renewed).

SELECT *
  FROM okc_k_lines_b
 WHERE chr_id IN (SELECT id
                    FROM okc_k_headers_b
                   WHERE contract_number = :p_contract_number);
***********************************************************
C. Contract Subline Data 

Note: When you add a subline to a contract OKC_K_LINES_B is populated with data, some of the data created there for each subline is internal data.  Use the LSE_ID to restrict the data returned when querying.

C1. Query for all the sublines on a contract with a Level type that can be seen when authoring the contract (i.e. restricts to lines which have Level of Product, Site, Item, System, Customer or Site).  (Note that this query may appear to return duplicate lines, as the query on okc_k_headers_b will return more than one contract if the contract has been renewed). 

SELECT id
     , line_number
     , cle_id
     , sts_code
     , hidden_ind
     , DECODE( lse_id,  8, 'Party',  7, 'Item',  9, 'Product',  10, 'Site',  11, 'System',  35, 'Customer' ) "Level"
     , object_version_number
     , price_negotiated
     , price_level_ind
     , price_unit
     , price_unit_percent
     , price_type
     , currency_code
     , price_list_id
     , price_list_line_id
     , item_to_price_yn
     , pricing_date
     , date_terminated
     , start_date
     , end_date
  FROM okc_k_lines_b
 WHERE dnz_chr_id IN (SELECT id
                        FROM okc_k_headers_b
                       WHERE contract_number = :p_contract_number)
   AND lse_id IN (8, 7, 9, 10, 11, 35);
*****************************************************************
C2. Query for contract sublines for a given contract line only. Replace <parent line number> with the line number of the required contract line (e.g. 1, 2. 3), taken either from the contract form, or from query B2.  (Note that this query may appear to return duplicate lines, as the query on okc_k_headers_b will return more than one contract if the contract has been renewed).

SELECT id
     , line_number
     , cle_id
     , sts_code
     , DECODE( lse_id,  8, 'Party',  7, 'Item',  9, 'Product',  10, 'Site',  11, 'System',  35, 'Customer' ) "Level"
     , object_version_number
     , price_negotiated
     , price_level_ind
     , price_unit
     , price_unit_percent
     , price_type
     , currency_code
     , price_list_id
     , price_list_line_id
     , item_to_price_yn
     , pricing_date
     , date_terminated
     , start_date
     , end_date
  FROM okc_k_lines_b
 WHERE dnz_chr_id IN (SELECT id
                        FROM okc_k_headers_b
                       WHERE contract_number = :p_contract_number)
   AND cle_id IN (SELECT id
                    FROM okc_k_lines_b
                   WHERE chr_id IN (SELECT id
                    FROM okc_k_headers_b
                   WHERE contract_number = :p_contract_number)
   AND line_number = :p_parent_line_number)
   AND lse_id IN (8, 7, 9, 10, 11, 35);
***********************************************************
C3. This query returns the inventory item for a given contract subline where the Level = Product (i.e. the subline is for a particular install base instance).

SELECT kl.line_number
     , ks.name
     , i.segment1
  FROM okc_k_headers_b kh
     , okc_k_lines_b kl
     , okc_k_items ki
     , okc_line_styles_v ks
     , csi_item_instances c
     , mtl_system_items_b i
 WHERE kh.contract_number = :p_contract_number
   AND kh.contract_number_modifier IS NULL                                                                 --can be populated
   AND kh.id = kl.dnz_chr_id
   AND kh.id = ki.dnz_chr_id
   AND kl.id = ki.cle_id
   AND kl.lse_id = ks.id
   AND ki.jtot_object1_code IN ('OKX_CUSTPROD')
   AND c.last_vld_organization_id = i.organization_id
   AND TO_NUMBER( ki.object1_id1 ) = c.instance_id
   AND c.inventory_item_id = i.inventory_item_id;

***********************************************************
D. Contract Billing Data

D1. This query shows the billing invoice details. Note that -99 will be shown for invoice number if the 'Service Contracts Fetch Receivables Info For Billing' concurrent program has not been run after Autoinvoice has been run. 
SELECT DISTINCT d.contract_number
              , a.trx_number "Invoice Number"
              , TO_CHAR( b.date_billed_from
                       , 'DD-MON-YYYY HH24-MI' )
                   "Bill From"
              , TO_CHAR( b.date_billed_to
                       , 'DD-MON-YYYY HH24-MI' )
                   "Bill To"
              , b.amount
  FROM oks_bill_transactions a
     , oks_bill_txn_lines aa
     , oks_bill_cont_lines b
     , okc_k_lines_b c
     , okc_k_headers_b d
 WHERE a.id = aa.btn_id
   AND aa.bcl_id = b.id
   AND b.cle_id = c.cle_id
   AND c.dnz_chr_id = d.id
   AND d.id = '<contract id FROM query A1>';
********************************************************** 
D2. This query shows the billing transaction details. The data in this table is shown in the History tab of the Billing Schedule form in the contract.

For the bill_action, the codes have the following meanings:
Regular Invoice -RI,
Termination Credit - TR,
Averaging - AV,
Settlement Invoice - SRI,
Settlement Credit - STR. 
  SELECT hdr.contract_number "Contract"
       , hdr.contract_number_modifier "Modifier"
       , hdr.id
       , TO_CHAR( cont.creation_date
                , 'DD-MON-YYYY HH24:MI' )
            "Creation Date"
       , bill_action
       , btn_id "Billing Transaction ID"
       , amount
       , TO_CHAR( date_billed_from
                , 'DD-MON-YYYY' )
            "Date Billed From"
       , TO_CHAR( date_billed_to
                , 'DD-MON-YYYY' )
            "Date Billed To"
    FROM oks_bill_cont_lines cont
       , okc_k_lines_b line
       , okc_k_headers_b hdr
   WHERE hdr.id = line.dnz_chr_id
     AND cont.cle_id = line.id
     AND hdr.id = '<contract id from query A1>'
ORDER BY cont.creation_date;

*****************************************************************
D3. This query returns data about the contract Line ids corresponding to each invoice as well as invoice details.

SELECT bcl.id
     , bcl.cle_id
     , bcl.btn_id
     , bcl.bill_action
     , okl.id "Line id"
     , okh.id "Contract id"
     , btn.trx_number "Invoice"
     , bcl.date_billed_from
     , bcl.date_billed_to
  FROM oks_bill_cont_lines bcl
     , okc_k_lines_b okl
     , okc_k_headers_b okh
     , oks_bill_transactions btn
     , oks_bill_txn_lines btl
 WHERE okh.contract_number = :p_contract_number
   AND okh.id = okl.dnz_chr_id
   AND okl.cle_id IS NULL
   AND okl.id = bcl.cle_id
   AND btn.id = bcl.btn_id
   AND btl.btn_id = btn.id
   AND btl.bill_instance_number IS NOT NULL;

D4. This query returns information about what the contract billing schedule for a contract and can be used to investigate amounts expected to be billed in a billing period.

SELECT TO_CHAR( bcl.id )
     , TO_CHAR( bsl.id )
     , TO_CHAR( lvl.id )
     , lvl.date_start
     , bsl.date_billed_from
     , lvl.date_end
     , bsl.date_billed_to
     , bcl.date_next_invoice
     , lvl.date_transaction
     , lvl.date_to_interface
     , lvl.date_completed
     , TO_CHAR( rul_id )
     , TO_CHAR( lvl.parent_cle_id )
     , bsl.amount
  FROM oks_bill_sub_lines bsl
     , oks_bill_cont_lines bcl
     , oks_level_elements lvl
     , okc_k_lines_b kl
     , okc_k_headers_b kh
 WHERE kh.contract_number = :p_contract_number
   AND kl.dnz_chr_id = kh.id
   AND lvl.dnz_chr_id = kh.id
   AND bcl.cle_id = kl.id
   AND bcl.id = bsl.bcl_id
   AND lvl.cle_id = bsl.cle_id;


E. Receivables Interface Data

E1. Query to return all the data in the RA interface table for a given service contract.  This will return the data populated into the table by Service Contracts Main Billing.   Note that this query will not return any data if Autoinvoice has been run since the records are deleted from this table once they have been successfully processed by Autoinvoice.

SELECT *
  FROM ra_interface_lines_all
 WHERE sales_order = :p_contract_number;

F. Subscription Contracts

F1.  How to find the install base instance created for the subscription line item.  (Note that when you enter a subscription line, the application automatically creates an Oracle Install Base item instance.  This is what this query is retrieving).

SELECT osh.instance_id
     , okh.contract_number
     , okh.contract_number_modifier
     , okl.line_number
  FROM oks_subscr_header_b osh
     , okc_k_headers_b okh
     , okc_k_lines_b okl
 WHERE osh.dnz_chr_id = okh.id
   AND osh.cle_id = okl.id
   AND okl.chr_id = okh.id
   AND okh.contract_number = :p_contract_number
   AND NVL( okh.contract_number_modifier, '-' ) = NVL( :p_contract_modifier, '-' );

F2. Query to find the install base instances created by a Subscription Contract as a result of subscription fulfillment.

SELECT csi.instance_number
  FROM oks_subscr_elements ose
     , csi_item_instances csi
 WHERE ose.dnz_chr_id IN (SELECT id
                            FROM okc_k_headers_b
                           WHERE contract_number = :p_contract_number
                             AND NVL( contract_number_modifier, '-' ) = NVL( :p_contract_modifier, '-' ))
   AND ose.order_line_id = csi.last_oe_order_line_id;

F3. Query to find which subscription contract line created the install base instance, for a subscription fulfillment.

SELECT okh.contract_number
     , okh.contract_number_modifier
     , okl.line_number
  FROM oks_subscr_elements ose
     , csi_item_instances csi
     , okc_k_headers_b okh
     , okc_k_lines_b okl
 WHERE csi.instance_number = :p_instance_number
   AND ose.order_line_id = csi.last_oe_order_line_id
   AND okh.id = ose.dnz_chr_id
   AND okl.chr_id = okh.id
   AND okl.id = ose.dnz_cle_id;

G. Order Details for Contracts Created from Order Management

G1. Query which retrieves the order header id  and order line id for a given contract.  object1_id1 gives the order header id where jtot_object1_code = OKX_ORDERHEAD
and the order line id where jtot_object1_code = OKX_ORDERLINE

SELECT okl.id subline
     , okl.cle_id service_line
     , okl.dnz_chr_id
     , obj.object1_id1
     , obj.jtot_object1_code
  FROM okc_k_lines_b okl
     , okc_k_rel_objs_v obj
 WHERE okl.dnz_chr_id = obj.chr_id
   AND okl.dnz_chr_id = :p_contract_id_from_query_a1
   AND lse_id IN (7, 8, 9, 10, 11, 18, 25, 35);

G2. The table OKS_K_ORDER_DETAILS captures service contract details when a service is ordered in Order Management.

SELECT *
  FROM oks_k_order_details
 WHERE chr_id = '<contract id from query A1>';

Monday, March 17, 2014

How To Write Out Multiple Clob Fields > 32k To A File in 4K chunks? (Doc ID 358781.1)

DECLARE
  l_output UTL_FILE.file_type;
  l_amt    NUMBER DEFAULT 4000;
  l_offset NUMBER DEFAULT 1;
  position INTEGER := 1;
  contador INTEGER;
  l_length NUMBER :=0 ;
  x        VARCHAR2(32000);
  v_Clob   VARCHAR2(4000);
  t_Clob CLOB;
  CURSOR c1
  IS
    SELECT clob_field
    FROM clob_table;
  -- New Variable to monitor the 32K limit
  v_32k_monitor NUMBER := 0;
BEGIN
  contador:=0;
  OPEN C1;
  l_output := UTL_FILE.fopen ('MY_DIR2', 'outputfile2.txt', 'w', 32760);
  LOOP
    FETCH C1
    INTO t_clob;
    EXIT WHEN C1%NOTFOUND;
    l_length := DBMS_LOB.GETLENGTH(T_CLOB);
    DBMS_OUTPUT.PUT_LINE(l_length);
    position := 1;
    l_offset := 1;
    l_amt    := 4000;
    --Reset the v_32k_monitor value for each row.
    v_32k_monitor  := 0;
    WHILE (l_offset < l_length)
    LOOP
      IF (l_amt > (l_length - l_offset)) THEN
        l_amt  := l_length  - l_offset + 1;
      END IF;
      dbms_output.put_line ('l_amt: ' || l_amt);
      dbms_output.put_line ('l_offset: ' || l_offset);
      dbms_lob.read (t_clob, l_amt, l_offset, x);
      utl_file.putf(l_output, x);
      l_offset := l_offset + l_amt;
      position := position + 4000;
      x        := NULL;
      --Since data is written in 4K chunks v_32k_monitor increase by 4K
      v_32k_monitor := v_32k_monitor + 4000;
      --There has to be a Since data is written in 4K chunks v_32k_monitor
      -- increase by 4K
      IF (v_32k_monitor >= 32000) THEN
        -- A new line has to be added every 32k
        DBMS_OUTPUT.PUT_LINE('A new line added');
        utl_file.new_line(l_output);
        v_32k_monitor := 0;
      END IF;
    END LOOP;
    utl_file.new_line(l_output);
    utl_file.putf (l_output, '\n');
  END LOOP;
  UTL_FILE.fclose (l_output);
END;
/
**********************************************************************
DECLARE
  l_output UTL_FILE.file_type;
  l_amt    NUMBER DEFAULT 4000;
  l_offset NUMBER DEFAULT 1;
  position INTEGER := 1;
  contador INTEGER;
  l_length NUMBER :=0 ;
  x        VARCHAR2(32000);
  v_Clob   VARCHAR2(4000);
  t_Clob CLOB;
  CURSOR c1
  IS
    SELECT clob_field
    FROM clob_table;
BEGIN
  contador:=0;
  OPEN C1;
  l_output := UTL_FILE.fopen ('MY_DIR2', 'outputfile102.txt', 'wb', 32760);
  LOOP
    FETCH C1
    INTO t_clob;
    EXIT WHEN C1%NOTFOUND;
    l_length := DBMS_LOB.GETLENGTH(T_CLOB);
    DBMS_OUTPUT.PUT_LINE(l_length);
    position       := 1;
    l_offset       := 1;
    l_amt          := 4000;
    WHILE (l_offset < l_length)
    LOOP
      IF (l_amt > (l_length - l_offset)) THEN
        l_amt  := l_length  - l_offset + 1;
      END IF;
      dbms_output.put_line ('l_amt: ' || l_amt);
      dbms_output.put_line ('l_offset: ' || l_offset);
      dbms_lob.read (t_clob, l_amt, l_offset, x);
      UTL_FILE.PUT_raw(l_output, utl_raw.cast_to_raw(x), TRUE);
      l_offset := l_offset + l_amt;
      position := position + 4000;
      x        := NULL;
    END LOOP;
    UTL_FILE.PUT_raw(l_output, utl_raw.cast_to_raw(CHR(10)), TRUE);
  END LOOP;
  UTL_FILE.fclose (l_output);
END;

/

Friday, February 21, 2014

Sample Subscription Package used for Business event in Oracle applications.

CREATE OR REPLACE PACKAGE xx_delivery_subscription_pkg
AS
   FUNCTION subscription(
      p_subscription_guid        IN             RAW
    , p_event                    IN OUT NOCOPY  wf_event_t
   )
      RETURN VARCHAR2;
END xx_delivery_subscription_pkg;
/

CREATE OR REPLACE PACKAGE BODY xx_delivery_subscription_pkg
AS
   FUNCTION subscription(
      p_subscription_guid        IN             RAW
    , p_event                    IN OUT NOCOPY  wf_event_t
   )
      RETURN VARCHAR2
   IS
      l_event_name                                      VARCHAR2(2000);
      l_event_key                                       VARCHAR2(2000);
      l_err_text                                        VARCHAR2(3000);
      l_param_list                                      wf_parameter_list_t;
      l_param_name                                      VARCHAR2(240);
      l_param_value                                     VARCHAR2(2000);
      l_order_number                                    VARCHAR2(50);
   BEGIN
      l_param_list                                   := p_event.getparameterlist;
      l_event_name                                   := p_event.geteventname();
      l_event_key                                    := p_event.geteventkey();

      IF l_param_list IS NOT NULL
      THEN
         FOR i IN l_param_list.FIRST .. l_param_list.LAST
         LOOP
            l_param_name                                   := l_param_list(i).getname;
            l_param_value                                  := l_param_list(i).getvalue;
            DBMS_OUTPUT.put_line('Parameter Name : ' || l_param_name || 'Parameter Value : ' || l_param_value);

            BEGIN
               SELECT oh.order_number
                 INTO l_order_number
                 FROM wsh_delivery_details wdd
                    , oe_order_headers_all oh
                    , wsh_delivery_assignments wda
                    , wsh_new_deliveries wnd
                WHERE wdd.source_header_id = oh.header_id
                  AND wdd.delivery_detail_id = wda.delivery_detail_id
                  AND wnd.delivery_id = wda.delivery_id
                  AND wnd.delivery_id = l_param_value
                  AND wnd.status_code <> 'OP'
                  AND wdd.source_code = 'OE'
                  AND wdd.released_status = 'C';
            EXCEPTION
               WHEN OTHERS
               THEN
                  DBMS_OUTPUT.put_line('Unexpected Error : ' || SUBSTR(SQLERRM
                                                                     , 1
                                                                     , 250
                                                                      ));
            END;

            INSERT INTO xx_shiment_notification_stg
                 VALUES (l_param_value
                       , l_order_number
                        );
         END LOOP;

         COMMIT;
      END IF;

      RETURN 'SUCCESS';
   EXCEPTION
      WHEN OTHERS
      THEN
         RETURN 'ERROR';
   END subscription;
END xx_delivery_subscription_pkg;

Query to get the Menu,Submenu and function details For Oracle Menus

  SELECT second.application_id "App ID"
       , second.application_name "App Name"
       , second.responsibility_id "Resp ID"
       , second.responsibility_name "Responsibility"
       , second.menu_id "Menu ID"
       , second.user_menu_name "Main Menu Name"
       , second.entry_sequence "Seq"
       , second.prompt "Prompt"
       , second.function_id "Function ID"
       , second.user_function_name "Function"
       , second.func_descrip "Function Descrip"
       , second.sub_menu_id "SubMenu ID"
       , second.sub_menu_name "SubMenu Name"
       , second.sub_seq "Sub Seq"
       , second.sub_prompt "SubPrompt"
       , second.sub_func_id "SubFunction ID"
       , second.sub_func "SubFunction"
       , second.sub_func_descrip "SubFunction Descrip"
       , second.sub_sub_menu_id "Sub-SubMenu ID"
       , second.grant_flag "Grant Flag"
       , second.resp_end_date "Resp End Date"
       , DECODE( exc.rule_type
               , 'F', ( SELECT 'Ex F: ' || exc.action_id
                          FROM fnd_form_functions_vl fnc
                         WHERE fnc.function_id = exc.action_id
                           AND second.function_id = exc.action_id ) )
            excluded_function
       , DECODE( exc.rule_type
               , 'F', ( SELECT 'Ex SF: ' || exc.action_id
                          FROM fnd_form_functions_vl fnc
                         WHERE fnc.function_id = exc.action_id
                           AND second.sub_func_id = exc.action_id ) )
            excluded_sub_function
       , DECODE( exc.rule_type
               , 'M', ( SELECT 'Ex M: ' || exc.action_id
                          FROM fnd_form_functions_vl fnc
                         WHERE fnc.function_id = exc.action_id
                           AND second.menu_id = exc.action_id ) )
            excluded_menu
       , DECODE( exc.rule_type
               , 'M', ( SELECT 'Ex SM: ' || exc.action_id
                          FROM fnd_form_functions_vl fnc
                         WHERE fnc.function_id = exc.action_id
                           AND second.sub_menu_id = exc.action_id ) )
            excluded_sub_menu
       , DECODE( exc.rule_type
               , 'M', ( SELECT 'Ex SSM: ' || exc.action_id
                          FROM fnd_form_functions_vl fnc
                         WHERE fnc.function_id = exc.action_id
                           AND second.sub_sub_menu_id = exc.action_id ) )
            excluded_sub_sub_menu
    FROM (  SELECT FIRST.application_id
                 , FIRST.application_name
                 , FIRST.responsibility_id
                 , FIRST.responsibility_name
                 , FIRST.end_date AS resp_end_date
                 , FIRST.menu_id
                 , FIRST.user_menu_name
                 , FIRST.entry_sequence
                 , FIRST.prompt
                 , FIRST.function_id
                 , ffft.user_function_name
                 , ffft.description AS func_descrip
                 , FIRST.sub_menu_id
                 , fmv2.user_menu_name AS sub_menu_name
                 , fme2.entry_sequence AS sub_seq
                 , fmet2.prompt AS sub_prompt
                 , fme2.function_id AS sub_func_id
                 , ffft2.user_function_name AS sub_func
                 , ffft2.description AS sub_func_descrip
                 , fme2.sub_menu_id AS sub_sub_menu_id
                 , FIRST.grant_flag
              FROM (  SELECT fat.application_id
                           , fat.application_name
                           , fr.responsibility_id
                           , frt.responsibility_name
                           , fr.end_date
                           , fr.menu_id
                           , fmv.user_menu_name
                           , fme.entry_sequence
                           , fmet.prompt
                           , fme.sub_menu_id
                           , fme.function_id
                           , fme.grant_flag
                        FROM apps.fnd_application_tl fat
                           , apps.fnd_responsibility fr
                           , apps.fnd_menus_vl fmv
                           , apps.fnd_responsibility_tl frt
                           , apps.fnd_menu_entries fme
                           , apps.fnd_menu_entries_tl fmet
                       --joins and constant selection
                       WHERE fat.application_id = fr.application_id(+)
                         AND fr.menu_id = fmv.menu_id(+)
                         AND fr.responsibility_id = frt.responsibility_id(+)
                         AND fr.menu_id = fme.menu_id(+)
                         AND fme.menu_id = fmet.menu_id(+)
                         AND fme.entry_sequence = fmet.entry_sequence(+)
                         AND fmet.language = 'US'
                         --------------------------------------
                         -- add specific selection criteria  --
                         --------------------------------------
                         --and   fat.application_id = 840
                         --for DEVL  19080 rows
                         --and fr.responsibility_id = 51856
                         AND fat.application_id = &appid
                    ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) FIRST ---for application, responsibility and main menu info
                 , apps.fnd_menus_vl fmv2                                                                 ---for submenu info
                 , apps.fnd_menu_entries fme2
                 , apps.fnd_menu_entries_tl fmet2
                 , apps.fnd_form_functions_tl ffft                                                       ---for function info
                 , apps.fnd_form_functions_tl ffft2                                                   ---for subfunction info
             --left outer joins keep original records and add any sub menu and function info
             WHERE FIRST.function_id = ffft.function_id(+)
               AND FIRST.sub_menu_id = fmv2.menu_id(+)
               AND FIRST.sub_menu_id = fme2.menu_id(+)
               AND fme2.menu_id = fmet2.menu_id(+)
               AND fme2.entry_sequence = fmet2.entry_sequence(+)
               AND fme2.function_id = ffft2.function_id(+)
          ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) second -- adds any sub menu and function info
         LEFT OUTER JOIN apps.fnd_resp_functions exc                                                        ---for exclusions
            ON ( second.application_id = exc.application_id
            AND second.responsibility_id = exc.responsibility_id
            AND ( second.function_id = exc.action_id
              OR second.sub_func_id = exc.action_id
              OR second.menu_id = exc.action_id
              OR second.sub_menu_id = exc.action_id
              OR second.sub_sub_menu_id = exc.action_id ) )
ORDER BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21;