Showing posts with label query. Show all posts
Showing posts with label query. Show all posts

Monday, October 03, 2011

R12 E-Business Suite Suppliers Query - SQL to join Suppliers, Contacts, Banks

In the Oracle E-Business Suite (EBS) Release 12 the data model of Suppliers has become much more complex. The base tables have changed (Suppliers, Sites, Bank Accounts, Contacts) and some of the fields have become obsolete.

Here is a query to bring many of the Supplier attributes together, with focus on banks / bank accounts, payment methods, contacts, remittance delivery (email, notification method). Please post comments if you find any issues!

Adjust the WHERE clause on the first WITH query to return the suppliers that you need to report on. Hope this query helps someone out.

Add additional fields to the final query (or WITH queries as required.)

Update 29-Feb-2012: Outer join sites ss to payment methods pm.

with vendors as
(
select vendor_id
from   ap_suppliers
where  1=1
/* COMMENT / UNCOMMENT and UPDATE THE NEXT 5 LINES AS YOU REQUIRE */
--and    vendor_type_lookup_code = 'VENDOR'
--and    upper( vendor_name ) like 'VIRTUATE%'
and    creation_date between '01-JAN-2011' and '01-JAN-2012'
--and    enabled_flag = 'Y'
)
, vend as
(
select pv.vendor_id                 vendor_id
,      pv.vendor_name_alt           vendor_name_alt
,      pv.vendor_name               vendor_name
,      pv.segment1                  vendor_number
,      pv.vendor_type_lookup_code   vendor_type_lookup_code
from   ap_suppliers pv
where  pv.vendor_id in (select v.vendor_id from vendors v)
)
, site as
(
select ss.vendor_id                    vendor_id
,      ss.vendor_site_id               vendor_site_id
,      ss.vendor_site_code             vendor_site_code
,      ss.vendor_site_code_alt         vendor_site_code_alt
,      ss.vat_code                     tax_code
,      ss.vat_registration_num         vat_registration_num
,      t.name                          terms_name
,      ss.address_line1                ss_address_line1
,      ss.address_line2                ss_address_line2
,      ss.address_line3                ss_address_line3
,      ss.zip                          ss_zip          
,      ss.city                         ss_city         
,      ss.state                        ss_state        
,      ss.country                      ss_country      
,      ss.area_code                    ss_area_code    
,      ss.phone                        ss_phone        
,      ss.fax_area_code                ss_fax_area_code
,      ss.fax                          ss_fax          
,      ss.telex                        ss_telex
,      ss.pay_site_flag                ss_pay_site_flag
,      ss.primary_pay_site_flag        ss_primary_pay_site_flag
,      pm.remit_advice_delivery_method ss_remit_advice_deliv_meth
,      pm.remit_advice_email           ss_remit_advice_email
,      pm.remit_advice_fax             ss_remit_advice_fax
,      pm.payment_method_code          ss_payment_method_code
,      ss.remittance_email             ss_remittance_email
,      ss.supplier_notif_method        ss_supplier_notif_method
,      ps.addressee                    ss_addressee
,      ( select hcp.phone_area_code
         from   hz_contact_points hcp
         where  hcp.owner_table_id = ss.party_site_id
         and    hcp.owner_table_name = 'HZ_PARTY_SITES'
         and    hcp.phone_line_type = 'GEN'
         and    hcp.contact_point_type = 'PHONE'
         --and    hcp.created_by_module = 'AP_SUPPLIERS_API'
         and    rownum < 2 -- copied from OAF View Object 
       ) ss_hcp_phone_area_code
,      ( select hcp.phone_number
         from   hz_contact_points hcp
         where  hcp.owner_table_id = ss.party_site_id
         and    hcp.owner_table_name = 'HZ_PARTY_SITES'
         and    hcp.phone_line_type = 'GEN'
         and    hcp.contact_point_type = 'PHONE'
         --and    hcp.created_by_module = 'AP_SUPPLIERS_API'
         and    rownum < 2 -- copied from OAF View Object 
       ) ss_hcp_phone_number
,      ( select hcp.phone_area_code
         from   hz_contact_points hcp
         where  hcp.owner_table_id = ss.party_site_id
         and    hcp.owner_table_name = 'HZ_PARTY_SITES'
         and    hcp.phone_line_type = 'FAX'
         and    hcp.contact_point_type = 'PHONE'
         --and    hcp.created_by_module = 'AP_SUPPLIERS_API'
         and    rownum < 2 -- copied from OAF View Object 
       ) ss_hcp_fax_area_code
,      ( select hcp.phone_number
         from   hz_contact_points hcp
         where  hcp.owner_table_id = ss.party_site_id
         and    hcp.owner_table_name = 'HZ_PARTY_SITES'
         and    hcp.phone_line_type = 'FAX'
         and    hcp.contact_point_type = 'PHONE'
         --and    hcp.created_by_module = 'AP_SUPPLIERS_API'
         and    rownum < 2 -- copied from OAF View Object 
       ) ss_hcp_fax_number
from   ap_supplier_sites_all ss
,      ap_suppliers sup
,      ap_terms t
,      (
         select ss.vendor_site_id
              , payee.remit_advice_delivery_method
              , payee.remit_advice_email
              , payee.remit_advice_fax
              , pm.payment_method_code
         from   iby_external_payees_all payee
         ,      iby_ext_party_pmt_mthds pm
         ,      hz_party_sites ps
         ,      ap_supplier_sites_all ss
         where  payee.payee_party_id = ps.party_id
         and    payee.payment_function = 'PAYABLES_DISB'
         and    payee.party_site_id = ss.party_site_id
         and    payee.supplier_site_id = ss.vendor_site_id
         and    payee.org_id = ss.org_id
         and    payee.org_type = 'OPERATING_UNIT'
         and    ss.party_site_id = ps.party_site_id
         and    payee.ext_payee_id = pm.ext_pmt_party_id (+)
         and    pm.primary_flag (+) = 'N'
         and not exists
                ( select 1
                  from   iby_ext_party_pmt_mthds pm2
                  where  pm.ext_pmt_party_id = pm2.ext_pmt_party_id
                  and    pm2.primary_flag = 'Y'
                )
         union all
         select ss.vendor_site_id
              , payee.remit_advice_delivery_method
              , payee.remit_advice_email
              , payee.remit_advice_fax
              , pm.payment_method_code
         from   iby_external_payees_all payee
         ,      iby_ext_party_pmt_mthds pm
         ,      hz_party_sites ps
         ,      ap_supplier_sites_all ss
         where  payee.payee_party_id = ps.party_id
         and    payee.payment_function = 'PAYABLES_DISB'
         and    payee.party_site_id = ss.party_site_id
         and    payee.supplier_site_id = ss.vendor_site_id
         and    payee.org_id = ss.org_id
         and    payee.org_type = 'OPERATING_UNIT'
         and    ss.party_site_id = ps.party_site_id
         and    pm.ext_pmt_party_id = payee.ext_payee_id
         and    pm.primary_flag = 'Y'
       ) pm
,      hz_party_sites ps
where  sup.vendor_id in (select vendor_id from vendors)
and    sup.vendor_id = ss.vendor_id
and    ss.vendor_site_id = pm.vendor_site_id (+)
and    ss.party_site_id = ps.party_site_id (+)
and    ss.terms_id = t.term_id (+)
)
, cont as
(
select pv.vendor_id           vendor_id
,      pvs.vendor_site_id     vendor_site_id
,      hp.party_id            c_party_id
,      hp.person_first_name   c_first_name
,      hp.person_last_name    c_last_name
,      hp.person_title        c_person_title
,      hcpe.email_address     c_email_address
,      hcpp.phone_area_code   c_phone_area_code
,      hcpp.phone_number      c_phone_number
,      hcpf.phone_area_code   c_fax_area_code
,      hcpf.phone_number      c_fax_number
from   hz_parties hp
,      hz_relationships hzr
,      hz_contact_points hcpp
,      hz_contact_points hcpf
,      hz_contact_points hcpe
,      ap_suppliers pv
,      ap_supplier_sites_all pvs
,      hz_party_sites hps
where  hp.party_id = hzr.subject_id
and    hzr.relationship_type = 'CONTACT'
and    hzr.relationship_code = 'CONTACT_OF'
and    hzr.subject_type = 'PERSON'
and    hzr.subject_table_name = 'HZ_PARTIES'
and    hzr.object_type = 'ORGANIZATION'
and    hzr.object_table_name = 'HZ_PARTIES'
and    hzr.status = 'A'
and    hcpp.owner_table_name(+) = 'HZ_PARTIES'
and    hcpp.owner_table_id(+) = hzr.party_id
and    hcpp.phone_line_type(+) = 'GEN'
and    hcpp.contact_point_type(+) = 'PHONE'
and    hcpf.owner_table_name(+) = 'HZ_PARTIES'
and    hcpf.owner_table_id(+) = hzr.party_id
and    hcpf.phone_line_type(+) = 'FAX'
and    hcpf.contact_point_type(+) = 'PHONE'
and    hcpe.owner_table_name(+) = 'HZ_PARTIES'
and    hcpe.owner_table_id(+) = hzr.party_id
and    hcpe.contact_point_type(+) = 'EMAIL'
and    hcpp.status (+)='A'
and    hcpf.status (+)='A'
and    hcpe.status (+)='A'
and    hps.party_id = hzr.object_id
and    pvs.party_site_id = hps.party_site_id
and    pv.vendor_id = pvs.vendor_id
and    exists
       ( select 1
         from ap_supplier_contacts ascs
         where (ascs.inactive_date is null
         or ascs.inactive_date      > sysdate)
         and hzr.relationship_id    = ascs.relationship_id
         and hzr.party_id           = ascs.rel_party_id
         and hps.party_site_id      = ascs.org_party_site_id
         and hzr.subject_id         = ascs.per_party_id
       )
and    pv.vendor_id in (select vendor_id from vendors)
)
, bank as
(
select  pv.vendor_id                    vendor_id
,       ss.vendor_site_id               vendor_site_id
,       hopbank.bank_or_branch_number   bank_number
,       hopbranch.bank_or_branch_number branch_number
,       eba.bank_account_num            bank_account_num
,       eba.bank_account_name           bank_account_name
,       piu.start_date                  bank_use_start_date
,       piu.end_date                    bank_use_end_date
,       piu.order_of_preference         bank_priority
from    iby_ext_bank_accounts eba
,       iby_external_payees_all payee
,       iby_pmt_instr_uses_all piu
,       ap_supplier_sites_all ss
,       ap_suppliers pv
,       hz_organization_profiles hopbank
,       hz_organization_profiles hopbranch
where   1=1
and     eba.bank_id = hopbank.party_id
and     eba.branch_id = hopbranch.party_id
and     payee.payment_function = 'PAYABLES_DISB'
and     payee.party_site_id = ss.party_site_id
and     payee.supplier_site_id = ss.vendor_site_id
and     payee.org_id = ss.org_id
and     payee.org_type = 'OPERATING_UNIT'
and     payee.ext_payee_id = piu.ext_pmt_party_id
and     piu.payment_flow = 'DISBURSEMENTS'
and     piu.instrument_type = 'BANKACCOUNT'
and     piu.instrument_id = eba.ext_bank_account_id
and     piu.start_date < sysdate
and     ( piu.end_date is null or
          piu.end_date > sysdate
        )
and     ss.vendor_id = pv.vendor_id
and     pv.vendor_id in (select vendor_id from vendors)
)
-- select distinct v.*, s.*, c.*, b.*
select distinct v.vendor_id             supplier_id
,      v.vendor_number                  supplier_num
,      v.vendor_name                    supplier_name
,      v.vendor_type_lookup_code        supplier_type
,      s.terms_name                     terms_name
,      s.tax_code                       invoice_tax_code
,      s.vat_registration_num           vat_registration_num
,      s.vendor_site_code               site_code
,      s.ss_address_line1               address1
,      s.ss_address_line2               address2
,      s.ss_address_line3               address3
,      s.ss_city                        suburb
,      s.ss_state                       state
,      s.ss_zip                         post_code
,      s.ss_country                     country
,      s.ss_payment_method_code         payment_method
,      b.bank_account_name              bank_account_name
,      b.bank_number                    bank_number
,      b.branch_number                  branch_number
,      b.bank_account_num               bank_account_num
,      s.ss_remit_advice_email          remittance_email
,      s.ss_remit_advice_deliv_meth     notification_method
,      c.c_first_name                   contact_first_name
,      c.c_last_name                    contact_last_name
,      c.c_person_title                 contact_title
,      c.c_email_address                contact_email
,      c.c_phone_area_code              contact_ph_area_code
,      c.c_phone_number                 contact_ph_number
,      c.c_fax_area_code                contact_fax_area_code
,      c.c_fax_number                   contact_fax_number
from   vend v
,      site s
,      cont c
,      bank b
where  v.vendor_id = s.vendor_id (+)
and    s.vendor_id = b.vendor_id (+)
and    s.vendor_site_id = b.vendor_site_id (+)
and    s.vendor_id = c.vendor_id (+)
and    s.vendor_site_id = c.vendor_site_id (+)
and    nvl(b.bank_priority,-1) = (select nvl(min(bank_priority),-1)
                                  from   bank b2
                                  where  b2.vendor_id = b.vendor_id
                                  and    b2.vendor_site_id = b.vendor_site_id)
order by 3,1,2,4,5,6,7,8,9,10,11,12,13;

Catch ya!
Gareth
This is a post from Gareth's blog at http://garethroberts.blogspot.com

Related Posts

Thursday, August 11, 2011

Track and Trace E-Business Suite Concurrent Request - EBS Logs, O/S Process IDs, Locks

I often get asked to take a look at an Oracle eBusiness Suite concurrent request to see what it is doing, this can come from a few different angles:

  1. What requests are currently running?
  2. I have an operating system process that is taking too much CPU - what is it doing?
  3. Can you tell me where the request is at? I've clicked on the log but it doesn't show anything!
  4. My request is taking too long - can you check for blocking locks?

There are a number of strategies to track and trace where things are at for a running request, these include:

  1. Monitor the currently running requests in fnd_concurrent_requests
  2. Checking the v$sqlarea to see what SQL statement or PL/SQL is running
  3. Tailing the concurrent request log / output file while it is being written to near realtime - prior to request completing
  4. Checking for locks blocking the concurrent request

So without further ado, let's take a look at the following sweet query. UPDATE: 23-Aug-2012 fixed multi rows due to missing join on inst_id between gv$session and gv$process. Also note for non-RAC environments change gv$ to v$ and remove joins to sys.v_$active_instances:

set pages 9999 feed on lines 150
col user_concurrent_program_name format a40 head PROGRAM trunc
col elapsed format 9999
col request_id format 9999999 head REQUEST
col user_name format a12
col oracle_process_id format a5 head OSPID
col inst_name format a10
col sql_text format a30
col outfile_tmp format a30
col logfile_tmp format a30

REM *********************
REM **** RAC VERSION ****
REM *********************
select /*+ ordered */ 
       fcp.user_concurrent_program_name
,      fcr.request_id
,      round(24*60*( sysdate - actual_start_date )) elapsed
,      fu.user_name
,      fcr.oracle_process_id
,      sess.sid
,      sess.serial#
,      inst.inst_name
,      sa.sql_text
,      cp.plsql_dir || '/' || cp.plsql_out outfile_tmp
,      cp.plsql_dir || '/' || cp.plsql_log logfile_tmp
from   apps.fnd_concurrent_requests fcr
,      apps.fnd_concurrent_programs_tl fcp
,      apps.fnd_concurrent_processes cp
,      apps.fnd_user fu
,      gv$process pro
,      gv$session sess
,      gv$sqlarea sa
,      sys.v_$active_instances inst
where  fcp.concurrent_program_id = fcr.concurrent_program_id
and    fcp.application_id = fcr.program_application_id
and    fcr.controlling_manager = cp.concurrent_process_id
and    fcr.requested_by = fu.user_id (+)
and    fcr.oracle_process_id = pro.spid (+)
and    pro.addr = sess.paddr (+)
and    pro.inst_id = sess.inst_id (+)
and    sess.sql_address = sa.address (+)
and    sess.sql_hash_value = sa.hash_value (+)
and    sess.inst_id = inst.inst_number (+)
and    fcr.phase_code = 'R' /* only running requests */
;

REM *********************
REM ** NON-RAC VERSION **
REM *********************
select /*+ ordered */ 
       fcp.user_concurrent_program_name
,      fcr.request_id
,      round(24*60*( sysdate - actual_start_date )) elapsed
,      fu.user_name
,      fcr.oracle_process_id
,      sess.sid
,      sess.serial#
,      sa.sql_text
,      cp.plsql_dir || '/' || cp.plsql_out outfile_tmp
,      cp.plsql_dir || '/' || cp.plsql_log logfile_tmp
from   apps.fnd_concurrent_requests fcr
,      apps.fnd_concurrent_programs_tl fcp
,      apps.fnd_concurrent_processes cp
,      apps.fnd_user fu
,      v$process pro
,      v$session sess
,      v$sqlarea sa
where  fcp.concurrent_program_id = fcr.concurrent_program_id
and    fcp.application_id = fcr.program_application_id
and    fcr.controlling_manager = cp.concurrent_process_id
and    fcr.requested_by = fu.user_id (+)
and    fcr.oracle_process_id = pro.spid (+)
and    pro.addr = sess.paddr (+)
and    sess.sql_address = sa.address (+)
and    sess.sql_hash_value = sa.hash_value (+)
and    fcr.phase_code = 'R' /* only running requests */
;

PROGRAM                                   REQUEST ELAPSED USER_NAME    OSPID        SID    SERIAL# INST_NAME  SQL_TEXT                       OUTFILE_TMP                    LOGFILE_TMP
---------------------------------------- -------- ------- ------------ ----- ---------- ---------- ---------- ------------------------------ ------------------------------ ------------------------------
Workflow Background Process               2960551       1 VIRTUATE     24814        130      29699 APPLPROD1  BEGIN WF_ENGINE.BACKGROUNDCONC /usr/tmp/o0068194.tmp          /usr/tmp/l0068194.tmp
                                                                                                              URRENT(:errbuf,:rc,:A0,:A1,:A2
                                                                                                              ,:A3,:A4,:A5); END;

1 row selected.

From the above we can see key information:

  • The running Concurrent Request Program Name and Request_ID
  • The database node operating system process id (OSPID) so we can monitor usage via top / iostat / vmstat
  • The SID / Serial in case we want to kill the session via alter system kill session '130,29699';
  • The instance name the database session is running on in a RAC environment
  • The currently running SQL text
  • The temporary files where concurrent request log/out is being written to via utl_file while running. These files are copied over to the Concurrent Tier $APPLCSF/$APPLOUT and $APPLLOG after completion of the request.

We can break out the above into a few queries and procedures to drill into specific information information from the core EBS tables and DBA v$ views

1. Get concurrent requests running, temp files and Operating System PID

col user_concurrent_program_name format a40 head PROGRAM trunc
col elapsed format 9999
col request_id format 9999999 head REQUEST
col user_name format a12
col oracle_process_id format a5 head OSPID
select  fcp.user_concurrent_program_name
,       fcr.request_id
,       round(24*60*( sysdate - actual_start_date )) elapsed
,       fu.user_name
,       fcr.oracle_process_id
from    apps.fnd_concurrent_requests fcr
,       apps.fnd_concurrent_programs_tl fcp
,       apps.fnd_user fu
where   fcp.concurrent_program_id = fcr.concurrent_program_id
and     fcp.application_id = fcr.program_application_id
and     fu.user_id = fcr.requested_by
and     fcr.phase_code = 'R';

PROGRAM                                   REQUEST ELAPSED USER_NAME    OSPID
---------------------------------------- -------- ------- ------------ -----
Virtuate GL OLAP Data Refresh             2960541       5 VIRTUATE     21681

2. Get current running sql from instance (RAC inst_id/name) where request is running

col inst_name format a10
col sql_text format a30
col module format a20

REM *********************
REM **** RAC VERSION ****
REM *********************
select sess.sid
,      sess.serial#
,      sess.module
,      sess.inst_id
,      inst.inst_name
,      sa.fetches
,      sa.runtime_mem
,      sa.sql_text
,      pro.spid
from   gv$sqlarea sa
,      gv$session sess
,      gv$process pro
,      sys.v_$active_instances inst
where  sa.address = sess.sql_address
and    sa.hash_value = sess.sql_hash_value
and    sess.paddr = pro.addr
and    sess.inst_id = pro.inst_id
and    sess.inst_id = inst.inst_number (+)
and    pro.spid = &OSPID_from_running_request;

REM *********************
REM ** NON-RAC VERSION **
REM *********************

select sess.sid
,      sess.serial#
,      sess.module
,      sa.fetches
,      sa.runtime_mem
,      sa.sql_text
,      pro.spid
from   v$sqlarea sa
,      v$session sess
,      v$process pro
where  sa.address = sess.sql_address
and    sa.hash_value = sess.sql_hash_value
and    sess.paddr = pro.addr
and    pro.spid = &OSPID_from_running_request;

If you're running something that has long SQL statements, get the full SQL Statement by selecting from v$sqltext_with_newlines as follows

select t.sql_text
from   v$sqltext_with_newlines t
,      v$session s
where  s.sid = &SID
and    s.sql_address = t.address
order by t.piece

3. Find currently spooling temp file from request

col outfile format a30
col logfile format a30
select cp.plsql_dir || '/' || cp.plsql_out outfile
,      cp.plsql_dir || '/' || cp.plsql_log logfile
from  apps.fnd_concurrent_requests cr
,     apps.fnd_concurrent_processes cp
where cp.concurrent_process_id = cr.controlling_manager
and cr.request_id = &request_id;

OUTFILE                        LOGFILE
------------------------------ ------------------------------
/usr/tmp/PROD/o0068190.tmp     /usr/tmp/PROD/l0068190.tmp

REM Now tail log file on database node to see where it is at, near realtime
REM tail -f /usr/tmp/l0068190.tmp

Then on the Database node you can tail -f the above plsql_out or plsql_log files to see where program is at. Combine this with good logging techniques (date/time stamp on each entry) and you'll be able to know where your program is at.

If locks are the potential problem, then drill into those:

Currently held locks per concurrent request

set lines 150
col object_name format a32
col mode_held format a15
select /*+ ordered */
       fcr.request_id
,      object_name
,      object_type
,      decode( l.block
             , 0, 'Not Blocking'
             , 1, 'Blocking'
             , 2, 'Global'
             ) status
,      decode( v.locked_mode
             , 0, 'None'
             , 1, 'Null'
             , 2, 'Row-S (SS)'
             , 3, 'Row-X (SX)'
             , 4, 'Share'
             , 5, 'S/Row-X (SSX)'
             , 6, 'Exclusive'
             , to_char(lmode)
             ) mode_held
from   apps.fnd_concurrent_requests fcr
,      gv$process pro
,      gv$session sess
,      gv$locked_object v
,      gv$lock l
,      dba_objects d
where  fcr.phase_code = 'R'
and    fcr.oracle_process_id = pro.spid (+)
and    pro.addr = sess.paddr (+)
and    sess.sid = v.session_id (+)
and    v.object_id = d.object_id (+)
and    v.object_id = l.id1 (+)
;

REQUEST_ID OBJECT_NAME                      OBJECT_TYPE         STATUS       MODE_HELD
---------- -------------------------------- ------------------- ------------ ---------------
   1070780 VIRTUATE_GL_OLAP_REFRESH         TABLE               Not Blocking Exclusive

So there you have it - enough tools to keep you happy Track n Tracing! Maybe next time we'll look at tracing with bind / waits or PL/SQL Profiling concurrent programs

Catch ya!
Gareth
This is a post from Gareth's blog at http://garethroberts.blogspot.com

Related Posts

Tuesday, April 06, 2010

Environment Variables from database table - Oracle E-Business Suite

Are you running Oracle E-Business Suite (EBS) / Applications and want to get an operating system level environment variable value from a database table, for example for use in PL/SQL? Or perhaps to default a concurrent program parameter? Didn't think environment variables were stored in the database?

Try out out this query that shows you $FND_TOP:

select value
from   fnd_env_context
where  variable_name = 'FND_TOP'
and    concurrent_process_id = 
      ( select max(concurrent_process_id) from fnd_env_context );

VALUE
--------------------------------------------------------------------------------
/d01/oracle/VIS/apps/apps_st/appl/fnd/12.0.0

Or did you want to find out the Product "TOP" directories e.g the full directory path values from fnd_appl_tops under APPL_TOP?

col variable_name format a15
col value format a64
select variable_name, value
from   fnd_env_context
where  variable_name like '%\_TOP' escape '\'
and    concurrent_process_id = 
     ( select max(concurrent_process_id) from fnd_env_context )
order by 1;

VARIABLE_NAME   VALUE
--------------- ----------------------------------------------------------------
AD_TOP          /d01/oracle/VIS/apps/apps_st/appl/ad/12.0.0
AF_JRE_TOP      /d01/oracle/VIS/apps/tech_st/10.1.3/appsutil/jdk/jre
AHL_TOP         /d01/oracle/VIS/apps/apps_st/appl/ahl/12.0.0
AK_TOP          /d01/oracle/VIS/apps/apps_st/appl/ak/12.0.0
ALR_TOP         /d01/oracle/VIS/apps/apps_st/appl/alr/12.0.0
AME_TOP         /d01/oracle/VIS/apps/apps_st/appl/ame/12.0.0
AMS_TOP         /d01/oracle/VIS/apps/apps_st/appl/ams/12.0.0
AMV_TOP         /d01/oracle/VIS/apps/apps_st/appl/amv/12.0.0
AMW_TOP         /d01/oracle/VIS/apps/apps_st/appl/amw/12.0.0
APPL_TOP        /d01/oracle/VIS/apps/apps_st/appl
AP_TOP          /d01/oracle/VIS/apps/apps_st/appl/ap/12.0.0
AR_TOP          /d01/oracle/VIS/apps/apps_st/appl/ar/12.0.0
...

Or perhaps the full directory path to $APPLTMP?

select value
from   fnd_env_context
where  variable_name = 'APPLTMP'
and    concurrent_process_id = 
      ( select max(concurrent_process_id) from fnd_env_context );

VALUE
--------------------------------------------------------------------------------
/d01/oracle/VIS/inst/apps/VIS_demo/appltmp

NB: These queries assume your concurrent managers are running!

Catch ya!
Gareth
This is a post from Gareth's blog at http://garethroberts.blogspot.com

References

Update - Added example output and $APPLTMP output.

Monday, September 17, 2007

Query: Monthly billing on specific day of month

Just a quick challenge.
Had a minor brain overload last Friday, eventually came up with (I think) a sub-optimal query ...
Basic scenario is that I want a billing event to happen on the monthly anniversary of a event, and want a single SQL statement that, given the original and current date, will tell me whether I should be billing on that day.
Problem is that e.g. if original date if 31-Jan-07 then I should bill on the 28-Feb-07. Moreover if the original date is 28-Feb-07 then I should bill on 28-Jan-07. However, the when the original date is 28-Feb-07 the Oracle months_between function isn't suitable as it returns 1 for both the 28-Mar-07 and 31-Mar-07, as follows:

select months_between(to_date('28-JUL-2007'),to_date('28-FEB-2007')) m1
,      months_between(to_date('31-JUL-2007'),to_date('28-FEB-2007')) m2
from   dual;

        M1         M2
---------- ----------
         5          5

1 row selected.
Okay, so here's my solution ... with a loop to test for a year. Anyone got a better alternative to the core query?
set serverout on size 1000000
declare
 org_date date := '28-JAN-03';
 cur_date date := '01-JAN-04';
 l_status varchar2(1);
 l_count number := 0;
 l_pays  number := 0;
begin
 while true loop
  l_count := l_count+1;
  begin
   select 'Y' yes
   into   l_status
   from   dual
   where 
      (
        (to_number(to_char(org_date,'DD')) <= 28 and
         to_number(to_char(org_date,'DD')) = to_number(to_char(cur_date,'DD'))
        )
        or
        ( to_number(to_char(org_date,'DD')) = 29 and
          ( to_number(to_char(org_date,'DD')) = to_number(to_char(cur_date,'DD'))
            or
            ( to_number(to_char(last_day(cur_date),'DD')) < 29 and
              to_number(to_char(last_day(cur_date),'DD')) >= 28 and
              cur_date = last_day(cur_date)
            )
          )
        )
        or
        ( to_number(to_char(org_date,'DD')) = 30 and
          ( to_number(to_char(org_date,'DD')) = to_number(to_char(cur_date,'DD'))
            or
            ( to_number(to_char(last_day(cur_date),'DD')) < 30 and
              to_number(to_char(last_day(cur_date),'DD')) >= 28 and
              cur_date = last_day(cur_date)
            )
          )
        )
        or
        ( to_number(to_char(org_date,'DD')) = 31 and
          ( to_number(to_char(org_date,'DD')) = to_number(to_char(cur_date,'DD'))
            or
            ( to_number(to_char(last_day(cur_date),'DD')) < 31 and
              to_number(to_char(last_day(cur_date),'DD')) >= 28 and
              cur_date = last_day(cur_date)
            )
          )
        )
      );
   dbms_output.put_line('Billing org_date='||org_date||' cur_date='||cur_date);
   l_pays := l_pays + 1;
  exception
  when no_data_found then
   null;
  end;
  if l_count > 366 then
   exit;
  end if;
  cur_date := cur_date + 1;
 end loop;
 dbms_output.put_line('Payments = '||l_pays);
end;
/
Comments more than welcome!

Thursday, September 13, 2007

Query: Find scheduled or on hold concurrent requests

I've noticed a number of requests for finding scheduled concurrent requests via a single query. But there are various combinations of phase_code, status_code, hold_flag, requested_start_date, etc on the fnd_concurrent_requests table and others that determine the "real" Phase and Status as displayed in the View Requests form.

No worries, here's how we find the Scheduled Requests:

select request_id
from   fnd_concurrent_requests
where  status_code in ('Q','I')
and    requested_start_date > SYSDATE
and    hold_flag = 'N';

Or for a more detailed version, check out the following:

select fcp.concurrent_program_name
,      fcpt.user_concurrent_program_name
,      fcr.description
,      fcr.request_id
,      decode(fcr.phase_code
             ,'P',decode(fcr.hold_flag
                        ,'Y','Inactive'
                        ,fl_p.meaning
                        )
             ,fl_p.meaning
             ) phase
,      decode(fcr.phase_code
             ,'P',decode(fcr.hold_flag
                        ,'Y','On Hold'
                        ,decode(sign(fcr.requested_start_date - sysdate)
                               ,1,'Scheduled'
                               ,fl_s.meaning)
                  )
             ,fl_s.meaning
             ) status
,      fcr.requested_start_date
from   fnd_concurrent_requests fcr
,      fnd_concurrent_programs fcp
,      fnd_concurrent_programs_tl fcpt
,      fnd_lookups fl_p
,      fnd_lookups fl_s
where  1=1
and    fcr.phase_code = fl_p.lookup_code
and    fl_p.lookup_type = 'CP_PHASE_CODE'
and    fcr.status_code = fl_s.lookup_code
and    fl_s.lookup_type = 'CP_STATUS_CODE'
and    fcr.requested_start_date > sysdate
and    fcr.concurrent_program_id = fcp.concurrent_program_id
and    fcr.program_application_id = fcp.application_id
and    fcp.concurrent_program_id = fcpt.concurrent_program_id
and    fcpt.language = 'US'
and    fcp.application_id = fcpt.application_id
order by fcr.request_id desc;

Thanks to form FNDRSRUN.fmb, Trace/Tkprof and the following Metalink notes:

Now statuses and phases will be sorted!

Saturday, August 18, 2007

Document Attachments: Private Stuff

Noticed a few posts on Oracle forums about FND Attached Documents i.e. Oracle Applications/eBusiness Suite Attachments. Thought I'd post some unsupported code here just for reference, and a query for getting the attachments (text/documents) themselves.

How to attach a "Web Page" URL attachment to a Payables Invoice via FND Document Attachment Private API.

To use this code there are a few things that you'll need to change:
  1. In the fnd_global call change the variables to your required user_id, resp_id, resp_appl_id, or comment the call if not needed see my post if you're unsure of this
  2. The l_pk1_value which is ap_invoices_all.invoice_id
  3. The l_filename and l_description variables
  4. Possibly l_category_id: create an real example, check out examine and find the category_id you need to use.
  5. Remember to commit!
  6. Updated 6-Mar-2012: This code has been tested against 11.5.10.2, 12.0 and 12.1 (code differences noted in comments - only queries tested for R12.0/12.1), if you have a different version this may have changed. Note this is a customization via a private API so is unsupported.
declare
l_rowid rowid;
l_attached_document_id number;
l_document_id number;
l_media_id number;
l_category_id number := 291; -- Invoice Internal
l_pk1_value fnd_attached_documents.pk1_value%TYPE := '63227';
l_description fnd_documents_tl.description%TYPE   := 'Gareth Document Attach Demo';
l_filename fnd_documents_tl.file_name%TYPE := 'http://www.oracle.com/index.html';
l_seq_num number;
begin
-- Setup applications session
-- User = OPERATIONS
-- Resp = Payables, Vision Operations
-- App  = Payables
fnd_global.apps_initialize(1318,50554,200);

select FND_DOCUMENTS_S.nextval
into   l_document_id
from   dual;

select FND_ATTACHED_DOCUMENTS_S.nextval
into   l_attached_document_id
from   dual;

select nvl(max(seq_num),0) + 10
into   l_seq_num
from   fnd_attached_documents
where  pk1_value = l_pk1_value
and    entity_name = 'AP_INVOICES';

fnd_documents_pkg.insert_row
( X_ROWID                        => l_rowid
, X_DOCUMENT_ID                  => l_document_id
, X_CREATION_DATE                => sysdate
, X_CREATED_BY                   => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_DATE             => sysdate
, X_LAST_UPDATED_BY              => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_LOGIN            => fnd_profile.value('LOGIN_ID')
, X_DATATYPE_ID                  => 5 -- Web Page
, X_CATEGORY_ID                  => l_category_id
, X_SECURITY_TYPE                => 2
, X_PUBLISH_FLAG                 => 'Y'
, X_USAGE_TYPE                   => 'O'
, X_LANGUAGE                     => 'US'
, X_DESCRIPTION                  => l_description
, X_FILE_NAME                    => l_filename
, X_MEDIA_ID                     => l_media_id
);

fnd_documents_pkg.insert_tl_row
( X_DOCUMENT_ID                  => l_document_id
, X_CREATION_DATE                => sysdate
, X_CREATED_BY                   => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_DATE             => sysdate
, X_LAST_UPDATED_BY              => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_LOGIN            => fnd_profile.value('LOGIN_ID')
, X_LANGUAGE                     => 'US'
, X_DESCRIPTION                  => l_description
, X_FILE_NAME                    => l_filename
, X_MEDIA_ID                     => l_media_id
);

fnd_attached_documents_pkg.insert_row
( X_ROWID                        => l_rowid
, X_ATTACHED_DOCUMENT_ID         => l_attached_document_id
, X_DOCUMENT_ID                  => l_document_id
, X_CREATION_DATE                => sysdate
, X_CREATED_BY                   => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_DATE             => sysdate
, X_LAST_UPDATED_BY              => fnd_profile.value('USER_ID')
, X_LAST_UPDATE_LOGIN            => fnd_profile.value('LOGIN_ID')
, X_SEQ_NUM                      => l_seq_num
, X_ENTITY_NAME                  => 'AP_INVOICES'
, X_COLUMN1                      => null
, X_PK1_VALUE                    => l_pk1_value
, X_PK2_VALUE                    => null
, X_PK3_VALUE                    => null
, X_PK4_VALUE                    => null
, X_PK5_VALUE                    => null
, X_AUTOMATICALLY_ADDED_FLAG     => 'N'
, X_DATATYPE_ID                  => 5
, X_CATEGORY_ID                  => l_category_id
, X_SECURITY_TYPE                => 2
, X_PUBLISH_FLAG                 => 'Y'
, X_LANGUAGE                     => 'US'
, X_DESCRIPTION                  => l_description
, X_FILE_NAME                    => l_filename
, X_MEDIA_ID                     => l_media_id
);
end;
/

Where to the actual attachments/documents get stored for attachments?

Here are some queries to get back the Payables Invoice attachments of category "Invoice Internal" for a given invoice. Attachments of type Web Page (URL or Filename)
select fad_f.seq_num
,      fdt_f.file_name media_data_text
from   fnd_attached_documents fad_f
,      fnd_documents fd_f
,      fnd_documents_tl fdt_f
,      fnd_document_categories_tl fdct_f
where  1 = 1
and    fad_f.document_id = fd_f.document_id
and    fad_f.document_id = fdt_f.document_id
and    fdct_f.category_id = fd_f.category_id
and    fdct_f.user_name = 'Invoice Internal'
and    fd_f.datatype_id = 5
and    fad_f.entity_name = 'AP_INVOICES'
and    fad_f.pk1_value = '63227';
Attachments of type "Long Text"
select fad_f.seq_num
,      fdlt_f.media_id   media_id
,      fdlt_f.long_text media_data_text
from   fnd_attached_documents fad_f
,      fnd_documents fd_f
,      fnd_documents_tl fdt_f
,      fnd_document_categories_tl fdct_f
,      fnd_documents_long_text fdlt_f
where  1 = 1
and    fad_f.document_id = fd_f.document_id
and    fad_f.document_id = fdt_f.document_id
and    fdct_f.category_id = fd_f.category_id
and    fdt_f.media_id = fdlt_f.media_id /* R11i */
-- and    fd_f.media_id = fdlt_f.media_id /* R12 */
and    fdct_f.user_name = 'Invoice Internal'
and    fad_f.entity_name = 'AP_INVOICES'
and    fad_f.pk1_value = '63227';
Attachments of type "Short Text"
select fad_f.seq_num
,      fdst_f.media_id   media_id
,      fdst_f.short_text media_data_text
from   fnd_attached_documents fad_f
,      fnd_documents fd_f
,      fnd_documents_tl fdt_f
,      fnd_document_categories_tl fdct_f
,      fnd_documents_short_text fdst_f
where  1 = 1
and    fad_f.document_id = fd_f.document_id
and    fad_f.document_id = fdt_f.document_id
and    fdct_f.category_id = fd_f.category_id
and    fdt_f.media_id = fdst_f.media_id /* R11i */
-- and    fd_f.media_id = fdst_f.media_id /* R12 */
and    fdct_f.user_name = 'Invoice Internal'
and    fad_f.entity_name = 'AP_INVOICES'
and    fad_f.pk1_value = '63227';
Attachments of type "File"
select fad_l.seq_num
,      fl_l.file_id      media_id
,      fl_l.file_data    media_data_blob
from   fnd_attached_documents fad_l
,      fnd_documents fd_l
,      fnd_documents_tl fdt_l
,      fnd_document_categories_tl fdct_l
,      fnd_lobs fl_l
where  1 = 1
and    fad_l.document_id = fd_l.document_id
and    fad_l.document_id = fdt_l.document_id
and    fdct_l.category_id = fd_l.category_id
and    fdt_l.media_id = fl_l.file_id /* Release 11i */
-- and fd_l.media_id = fl_l.file_id /* Release 12 */
and    fad_l.entity_name = 'AP_INVOICES'
and    fdct_l.user_name = 'Invoice Internal'
and    fad_l.pk1_value = '63227';
Update: Added extra line to file query for R12. Update: In case anyone needs to delete any attachments here's an example (thanks to Mark L):
declare
l_entity_name varchar2(20):= 'PO_LINES';  -- This defines the PO_LINES entity
l_pk1_value varchar2 (20) := '200487';    -- PO_LINE_ID items are attached to
l_delete_document_flag varchar2 (1) := 'Y';    -- Delete the document
begin
--fnd_global.apps_initialize(0,20420,1); -- SYSADMIN System Administrator
fnd_attached_documents2_pkg.delete_attachments
( X_entity_name                  => l_entity_name
, X_pk1_value                    => l_pk1_value
, X_delete_document_flag         => l_delete_document_flag
);
end;
/
commit;
Happy Attaching!

Wednesday, July 18, 2007

Query: eBiz Setup of Books/Chart of Accounts keyflex segments

Thought I'd post a few of the common queries I run to save some retyping... here's the first! When I want a quick overview of the structure of clients chart of accounts, the following query comes in handy. Shows chart of accounts, set of books, accounting flexfield segments in use and their attributes, value sets for the key flexfield segments. Looks big, but quite a bit of repetition here to get the segment attributes.

select sob.name sob_name
,      sob.set_of_books_id sob_id
,      sob.chart_of_accounts_id coa_id
,      fifst.id_flex_structure_name struct_name
,      ifs.segment_name
,      ifs.application_column_name column_name
,      sav1.attribute_value  BALANCING
,      sav2.attribute_value COST_CENTER
,      sav3.attribute_value NATURAL_ACCOUNT
,      sav4.attribute_value  INTERCOMPANY
,      sav5.attribute_value SECONDARY_TRACKING
,      sav6.attribute_value GLOBAL
,      ffvs.flex_value_set_name
,      ffvs.flex_value_set_id
from   fnd_id_flex_structures fifs
,      fnd_id_flex_structures_tl fifst
,      fnd_segment_attribute_values  sav1
,      fnd_segment_attribute_values sav2
,      fnd_segment_attribute_values sav3
,      fnd_segment_attribute_values  sav4
,      fnd_segment_attribute_values sav5
,      fnd_segment_attribute_values sav6
,      fnd_id_flex_segments ifs
,      fnd_flex_value_sets ffvs
,      gl_sets_of_books sob
where  1=1
and    fifs.id_flex_code = 'GL#'
and    fifs.application_id =  fifst.application_id
and    fifs.id_flex_code = fifst.id_flex_code
and    fifs.id_flex_num = fifst.id_flex_num
and    fifs.application_id =  ifs.application_id
and    fifs.id_flex_code = ifs.id_flex_code
and    fifs.id_flex_num = ifs.id_flex_num
and    sav1.application_id =  ifs.application_id
and    sav1.id_flex_code = ifs.id_flex_code
and    sav1.id_flex_num = ifs.id_flex_num
and    sav1.application_column_name =  ifs.application_column_name
and    sav2.application_id =  ifs.application_id
and    sav2.id_flex_code = ifs.id_flex_code
and    sav2.id_flex_num = ifs.id_flex_num
and    sav2.application_column_name =  ifs.application_column_name
and    sav3.application_id =  ifs.application_id
and    sav3.id_flex_code = ifs.id_flex_code
and    sav3.id_flex_num = ifs.id_flex_num
and    sav3.application_column_name =  ifs.application_column_name
and    sav4.application_id =  ifs.application_id
and    sav4.id_flex_code = ifs.id_flex_code
and    sav4.id_flex_num = ifs.id_flex_num
and    sav4.application_column_name =  ifs.application_column_name
and    sav5.application_id =  ifs.application_id
and    sav5.id_flex_code = ifs.id_flex_code
and    sav5.id_flex_num = ifs.id_flex_num
and    sav5.application_column_name =  ifs.application_column_name
and    sav6.application_id =  ifs.application_id
and    sav6.id_flex_code = ifs.id_flex_code
and    sav6.id_flex_num = ifs.id_flex_num
and    sav6.application_column_name =  ifs.application_column_name
and    sav1.segment_attribute_type =  'GL_BALANCING'
and    sav2.segment_attribute_type = 'FA_COST_CTR'
and    sav3.segment_attribute_type = 'GL_ACCOUNT'
and    sav4.segment_attribute_type  = 'GL_INTERCOMPANY'
and    sav5.segment_attribute_type =  'GL_SECONDARY_TRACKING'
and    sav6.segment_attribute_type =  'GL_GLOBAL'
and    ifs.id_flex_num = sob.chart_of_accounts_id
and    ifs.flex_value_set_id = ffvs.flex_value_set_id
-- comment the next expression to show all books
-- currently it show the info for the site level set profile option value
and    sob.set_of_books_id = 
        nvl(fnd_profile.value('GL_SET_OF_BKS_ID'),sob.set_of_books_id)
order by  sob.name, sob.chart_of_accounts_id, ifs.application_column_name;
And just for good measure here's the sample output from 11.5.10.2 Vision Demo instance.
SOB_NAME                           SOB_ID     COA_ID STRUCT_NAME                    SEGMENT_NAME                   COLUMN_NAME                    B C N I S G FLEX_VALUE_SET_NAME                                          FLEX_VALUE_SET_ID
------------------------------ ---------- ---------- ------------------------------ ------------------------------ ------------------------------ - - - - - - ------------------------------------------------------------ -----------------
Vision Operations (USA)                 1        101 Operations Accounting Flex     Company                        SEGMENT1                       Y N N Y N Y Operations Company                                                     1002470
Vision Operations (USA)                 1        101 Operations Accounting Flex     Department                     SEGMENT2                       N Y N N N Y Operations Department                                                  1002471
Vision Operations (USA)                 1        101 Operations Accounting Flex     Account                        SEGMENT3                       N N Y N N Y Operations Account                                                     1002472
Vision Operations (USA)                 1        101 Operations Accounting Flex     Sub-Account                    SEGMENT4                       N N N N N Y Operations Sub-Account                                                 1002473
Vision Operations (USA)                 1        101 Operations Accounting Flex     Product                        SEGMENT5                       N N N N N Y Operations Product                                                     1002474
Nice.