Tuesday, August 26, 2014

Special and Pair validation types

I am working on an article about flexfields and flexfield validation.
Even though the article is not yet finished, I thought the part about ‘SPECIAL’ and ‘PAIR’ validation types might be interesting enough. Many people seem to think they can only use the seeded validation sets. However, you can also create your own validation sets. And their options are very powerful. So I wanted to publish this part of the article as a prelude to the full story.

Special Validation

Special validation is used to provide flexfield functionality for a single value. What that means is that you can have for example a concurrent program parameter that will be filled with a Key flexfield value, or a range of flexfield values.
Let’s go back to the Key Flexfield. We know that they are combinations of different segment values that are stored in a separate combination table.
When you want to submit a key-flexfield combination as a parameter to a concurrent program, you can code your own validation for the separate values. But you’ll be missing the nice functionality that gives you pop-ups, a validation over the resulting combination and if needed the ID-value for the flexfield combination.
That is possible with a ‘Special’ validation type.
The special validation uses a number of user exits to enter, validate and query keyflex segments. With special validation, you will be able to enter one or more segment values for a key flexfield. To enter these segment values, 3 user exits can be used. They are: ‘POPID’, ‘VALID’ and ‘LOADID’.
POPID is used to enable the user to enter the flexfield segment value. It is called when the users cursor enters the segment value field. With this user exit, you decide which segment values should be shown, and how they should be shown.
 VALID is called when the user exits the segment value, or confirms the chosen flexfield combination. It validates the entered value against the values existing in the key flexfield table.
LOADID is optional, and it can be used to choose which information will be returned as flexfield value. This can be the concatenated segments, or the id-value for the flexfield combination or segment values.
These 3 user exits can be assigned to 3 ‘events’. There are more events possible, but they are either not yet in use, or their use is not yet supported. So we will only use ‘Validate’, ‘Edit’ and ‘Load’.
Sounds complicated, so far? Don’t worry; this is not an easy validation. But we’ll build some examples to give you an idea. First we start with building a very easy special validation. This will be built on our Code Combination key flexfield. We’ll be using a concurrent program ‘Test Flex Validation’ program to see our different options.
This program is based on the following procedure:
CREATE OR REPLACE PROCEDURE XXX_TEST_FLEXFIELD_PARAMS
( errbuf   out varchar2
, retcode  out varchar2
, p_flex   in  varchar2
, p_flex2  in  varchar2 := ‘XXX’
, p_flex3  in  varchar2 := ‘XXX’
, p_flex4  in  varchar2 := ‘XXX’
, p_flex5  in  varchar2 := ‘XXX’
) IS
BEGIN
   FND_FILE.PUT_LINE(FND_FILE.OUTPUT,p_flex);
   FND_FILE.PUT_LINE(FND_FILE.OUTPUT,p_flex2);
   FND_FILE.PUT_LINE(FND_FILE.OUTPUT,p_flex3);
   FND_FILE.PUT_LINE(FND_FILE.OUTPUT,p_flex4);
   FND_FILE.PUT_LINE(FND_FILE.OUTPUT,p_flex5);
END;

This will only write the parameter value to the output of the request. To use flexfields as parameters for concurrent programs, we need to define a value set based on them.
We will start with the barest setup to enter a key-flexfield combination. For this article, we use the accounting flexfield, with code ‘GL#’  and id-num ‘101’.
In this case, we have the following definition:

So what does this mean?
The first box is for the edit event. This will be triggered when the user enters the cursor into the field with this value set.
FND POPID         This is the user exit to pop up a flexfield screen, and let the user enter the flexfield values.
CODE="GL#"     This is the flexfield code for the key flexfield that we will be using.
APPL_SHORT_NAME="SQLGL" The short name for the application the flexfield belongs too. Together with ‘Code’, this will identify the flexfield itself.
NUM="101"       The id-number for the flexfield structure. If you have only a single structure flexfield, it is optional. For flexfields enabled for multiple structures, you need to enter the id-number.
VALIDATE="PARTIAL"   Validate can be ‘None’, ‘Partial’ or ‘Full’. None means the combination is not validated. Partial means that the separate segments are validated, there is no validation if the combination exists. Full means that segments and combination will be checked, and if a new value is entered, this will be inserted into the key flexfield table.
SEG=":!VALUE"                This is the forms field that will be used to store the value of the segments.
The second box is for the ‘Validation’ event. This code will be called when the user navigates out of the field, or submits the entire combination.
Now when we set this value set as a parameter for our concurrent program, we can see how the validation works:

Now when we run the program, we get this pop-up:

We have all the functionality of the key flexfield. We can use the ‘Combinations’ button to search for existing combinations, and all separate segments will be validated, as will be the final combination.
When we submit a value to our program, it will show the concatenated segments as the value of our parameter:

Now let’s see some more features of this validation. For example, we’d like to have the value of the combination id. (CODE_COMBINATION_ID in our case, since we use the Accounting Flexfield).
To get that, we need to add the LOADID user exit:
 
The ‘Load’ event will get the combination-id from the flexfield table. This is only possible for the ‘VALIDATE=”FULL”, since it will validate the whole combination. Also we need to set the ID=”:!ID”. This will populate the :!ID column with the ID value of the combination.
Finally, I added the ‘DINSERT=”NO” ‘, because we don’t want to allow insertion of new code combinations from this value set. (And Validation=”FULL” by default inserts new combinations into the flexfield column).
Now when we run the concurrent request, we see that the parameter value is the code_combination_id instead of the concatenated segments:

With these user exits it is also possible to select just a number of segments, instead of the whole combination. For this we remove the ‘Load’ / ‘LOADID’ part again.
Then we add a ‘DISPLAY=”x” ‘ to the ‘Edit’ and ‘Validate’ user exits. The “display” parameter is defaulting to ‘ALL’. But you can also specify separate segments by their sequence number or names. In our case, we display the first 2 segments:

Now when we run the concurrent program, we get a pop-up for only the first 2 values:

A very nice feature (at least as far as I’m concerned) is the use of a where clause on the combination values. Consider the following ‘Enter’ code:
FND POPID
CODE="GL#"
NUM="101"
APPL_SHORT_NAME="SQLGL"
VALIDATE="FULL"
TITLE="Special Validation Key"
ID=":!ID"
SEG=":!VALUE"
DESC=":!MEANING"
WHERE="segment2 not like '1%' "

The “WHERE” clause prevents us from choosing combinations that have a segment2 starting with ‘1’. When we run our concurrent program with this, and choose the combinations:


There is no Dpt starting with 1.

When we add the “WHERE”-clause to the validation event too, it will prevent us from entering the values manually:



The last feature that we’ll look into is the use of a pl/sql validation through the special validation routines. By using the user-exit PLSQL, we can call an anonymous PL/SQL block in our ‘Validation’ event. I created a value set with the following function for the ‘Validation’ event:

FND PLSQL " declare
  v_value varchar2( 10 ) := :!value ;
  v_sum number;
  v_valid boolean;
begin
   v_sum:=0;
   for i in 1..length(v_value) loop
    v_sum :=v_sum+(length(v_value)+1-i)*substr(v_value,i,1);
  end loop;
  if mod(v_sum,11)=0 then
     v_valid := TRUE;
  else
     v_valid:=FALSE;
  end if;
  if not v_valid then
      fnd_message.set_name('FND','FND_GENERIC_MESSAGE' );
      fnd_message.set_token('MESSAGE','This is not a valid bank account');
      fnd_message.raise_error;
  end if;
END; "


This PL/SQL procedure validates a (Dutch) bank account number. If it does need pass the test, a message will be displayed. This gives you almost unlimited possibilities for validating entered data.
As you can see, it is only a ‘Validate’ event. Because we don’t need any special functionality for entering the data. We can limit the entry to numbers only on the ‘Validation Set’ main page.

Now when we use this value set for our concurrent program, we can only enter valid dutch bank accounts:


And


The list of parameters for the user exits is longer than this. So we won’t be going through all the possibilities. You can check the Developers Guide and the Flexfield guide for a complete listing of options. (Did you notice the flexfield title that I sneaked into the pop-up? Try and find the option for that!)
Please try the different options for yourself, and realize the possibilities of the special validation.

 

Pair Validation

Meanwhile, we’ll continue to the ‘Pair’ validation. The pair validation is very much like the ‘special’ validation. It uses the same kind of user exits, but this time, a range of segment values or combinations is selected.
Let’s first create a range of the account segment. Instead of using POPID and VALID, we use POPIDR and VALIDR. The R-version of the user-exits automatically create a range.
Of course we need 2 parameters to set the range. However, we need only one validation set.
I created the validation set ‘XXX_PAIR_VAL’. I entered only the edit and validate events:

The next step is to set the parameters for both the low and high value. Both parameters have the validation set ‘XXX_PAIR_VAL’.

Now when we run the program, we can enter a range. This includes validation that the high value is indeed higher or equal to the low value.

Of course the concurrent program will receive the values for 2 parameters.

When we use the full validation we can enter a range of the whole account combination. Note that we cannot use the FULL validation for pair-validation. Because that would mean the use of the combination-id from the flexfield table and based on the combination-id’s you cannot build a range.

So we can only use PARTIAL and NONE for the validation. For that same reason, I have not yet had a reason to use a LOAD event for PAIR validation. It is however allowed to use one.

I created a PAIR validation for the whole accounting range as follows:
 

When used in the concurrent program, it will indeed allow us to enter a range of all segments:


That completes the chapter on PAIR validation too.

Wednesday, August 6, 2014

O2C Flow SQL Query Link

select ooha.order_number,ooha.org_id,
hca.account_name,
hp.party_name "Customer Name",
hcasab.orig_system_reference BILL_TO_ORIG_REF,
hpsb.status BILL_TO_STATUS,
'ADDRESS1 - '||bill_loc.address1||','||CHR(10)|| 'ADDRESS2 - '||bill_loc.address2||','||CHR(10)||
'ADDRESS3 - '||bill_loc.address3||','||CHR(10)|| 'CITY - '||bill_loc.city||','||CHR(10)||
'POSTAL CD- '||bill_loc.postal_code||','||CHR(10)|| 'COUNTRY - '|| bill_loc.country BILL_TO_ADDRESS,
hcasas.orig_system_reference SHIP_TO_ORIG_REF,
hpss.status SHIP_TO_STATUS,
'ADDRESS1 - '||ship_loc.address1||','||CHR(10)|| 'ADDRESS2 - '||ship_loc.address2||','||CHR(10)||
'ADDRESS3 - '||ship_loc.address3||','||CHR(10)|| 'CITY - '||ship_loc.city||','||CHR(10)||
'POSTAL CD- '||ship_loc.postal_code||','||CHR(10)|| 'COUNTRY - '|| ship_loc.country SHIP_TO_ADDRESS,
oola.inventory_item_id,oola.ordered_item,
msib.description item_description,
wnd.name delivery_number,
rct.trx_number "AR Invoice Number",
acr.receipt_number "AR Receipt Number",
gjh.ledger_id,
gjh.name
from oe_order_headers_all ooha,
oe_order_lines_all oola,
hz_parties hp,
hz_cust_accounts hca,
hz_party_sites hpss,
hz_party_sites hpsb,
hz_locations bill_loc,
hz_locations ship_loc,
hz_cust_acct_sites_all hcasab,
hz_cust_acct_sites_all hcasas,
hz_cust_site_uses_all hzsuab,
hz_cust_site_uses_all hzsuas,
mtl_system_items_b msib,
wsh_delivery_details wdd,
wsh_new_deliveries wnd,
wsh_delivery_assignments wda,
ra_customer_trx_all rct,
ra_customer_trx_lines_all rctl,
ra_cust_trx_line_gl_dist_all rctld,
ar_cash_receipts_all acr,
xla.xla_transaction_entities xte,
xla_events xe,
xla_ae_headers xah,
xla_ae_lines xal,
xla_distribution_links xdl,
gl_import_references gir,
gl_je_batches gjb,
gl_je_headers gjh,
gl_je_lines gjl
where ooha.order_number = :SalesOrderNumber --Right click :RequitionNumber from Toad Enable Prompt For Substitution Variables
and ooha.org_id = 204
and hca.cust_account_id = ooha.sold_to_org_id
and hp.party_id = hca.party_id
and hpss.party_id = hca.party_id
and hpsb.party_id = hca.party_id
and bill_loc.location_id = hpss.location_id
and ship_loc.location_id = hpsb.location_id
AND hcasas.cust_account_id = hca.cust_account_id
AND hcasab.cust_account_id = hca.cust_account_id
AND hcasas.party_site_id = hpss.party_site_id
AND hcasab.party_site_id = hpsb.party_site_id
and hzsuas.cust_acct_site_id = hcasas.cust_acct_site_id
and hzsuab.cust_acct_site_id = hcasab.cust_acct_site_id
and hzsuas.site_use_id = ooha.ship_to_org_id
and hzsuab.site_use_id = ooha.invoice_to_org_id
and wda.delivery_id = wnd.delivery_id(+)
and wdd.delivery_detail_id = wda.delivery_detail_id
and wdd.source_header_id = ooha.header_id
and wdd.source_line_id = oola.line_id
and wdd.organization_id = msib.organization_id(+)
and wdd.inventory_item_id =msib.inventory_item_id(+)
and rct.interface_header_attribute1 = to_char(ooha.order_number)
and rct.org_id = ooha.org_id
and rctl.customer_trx_id = rct.customer_trx_id
and rctl.sales_order = to_char(ooha.order_number)
and rctld.customer_trx_id = rct.customer_trx_id
and rctld.customer_trx_line_id = rctl.customer_trx_line_id
and acr.receipt_number = 'G-1001'
and acr.pay_from_customer = rct.sold_to_customer_id
and acr.org_id = ooha.org_id
and acr.customer_site_use_id = rct.bill_to_site_use_id
and xte.transaction_number = acr.receipt_number
and xte.entity_code = 'RECEIPTS'
and xe.entity_id = xte.entity_id
and xah.event_id = xe.event_id
and xal.ae_header_id = xah.ae_header_id
and xal.accounting_class_code = 'CASH'
and xdl.ae_header_id = xah.ae_header_id
and xdl.ae_line_num = xal.ae_line_num
--and xdl.source_distribution_id_num_1
and gir.reference_5 = xte.entity_id -- Entity Id
and gir.reference_6 = to_char(xe.event_id) --Event Id
and gir.reference_7 = to_char (xah.ae_header_id) -- AE Header Id
and gir.gl_sl_link_id = xal.gl_sl_link_id
and gir.created_by = 1318
and gjb.je_batch_id = gir.je_batch_id
and gjh.je_batch_id=gjb.je_batch_id
and gjh.je_header_id = gir.je_header_id
and gjl.je_header_id=gjh.je_header_id
and gjl.je_line_num= gir.je_line_num;

Wednesday, July 23, 2014

Forms trigger Firing Sequence


Forms trigger Firing Sequence

Introduction
------------

This document lists the order in which triggers fire in Oracle Forms 4.5:
o The first column, Action, describes the function to be performed
(e.g. deleting a record).
o The second column, Trigger Firing Order, describes the order
in which triggers fire after a function is performed.
o The third column, Level, describes the level (form, block, item)
at which the trigger fires. This was accomplished by creating a form
with all the triggers invoked. If a trigger could fire at all levels,
it was included at all levels. Such a trigger fires at the lowest level
at which it is defined.

Key triggers and triggers which fire via buttons or check boxes are
not included.

This bulletin does not cover every contingency and covers only the
most commonly used actions.
Action Trigger Firing Order Level
------ -------------------- -----

Runform 

1. Pre-Logon Form
2. On-Logon Form
3. Post-Logon Form
4. Pre-Form Form
5. When-Create-Record Block
6. Pre-Block Block
7. Pre-Record Block
8. Pre-Text-Item Item
9. When-New-Form-Instance Form
10. When-New-Block-Instance Block
11. When-New-Record-Instance Block
12. When-New-Item-Instance Item

***********

Enter Query 


1. Post-Text-Item Item
2. Post-Record Block
3. When-Clear-Block Block
4. When-New-Record-Instance Block
5. When-New-Item-Instance Item

Note: If you define the Key-ENTQRY trigger, this is the only trigger
which fires in an Enter Query situation.


*****************

Execute Query

After Enter Query 1. Pre-Query Block
2. Pre-Select Block
3. On-Select Block
4. When-Clear-Block Block
5. Post-Select Block
6. On-Fetch Block
7. On-Close Form
8. When-Clear-Block Block

Note: If you define the Key-EXEQRY trigger, this is the only trigger
which fires in an Execute Query situation.


*************

Execute Query Without Enter

Query 1. Post-Text-Item Block
2. Pre-Query Block
3. Pre-Select Block
4. On-Select Block
5. Post-Select Block
6. On-Fetch Block
7. On-Close Form
8. When_Create_Record Block
9. Pre-Record Block
10. Pre-Text-Item Item
11. When-New-Record-Instance Block
12. When-New-Item-Instance Item


****

Exit 1. Post-Text-Item Item

2. Post-Record Block
3. Post-Block Block
4. Post-Form Form
5. On-Rollback Form
6. Pre-Logout Form
7. On-Logout Form
8. Post-Logout Form


**************

Next Field and Previous field 

1. When-New-Item-Instance Item


***************

Next Record and Previous Record 

1. When-New-Record-Instance Block
2. When-New-Item-Instance Item

**************

Next Block and Previous Block 

1. Post-Text-Item Item
2. Post-Record Block
3. Post-Block Block
4. When-Create-Record Block
5. Pre-Block Block
6. Pre-Record Block
7. Pre-Text-Item Block
8. When-New-Block-Instance Block
9. When-New-Record-Instance Block
10. When-New-Item-Instance Form


*******************

Records Are Queried 

1. Post-Query Block
2. Post-Change Block
3. Post-Change Item
4. Post-Change Block
5. Post-Change Block
Go back to Post-Query

NOTE: This cycle is repeated for each record retrieved.


**********************

No Records Are Queried 

1. When-New-Record-Instance Block
2. When-New-Item-Instance Item

NOTE: To observe this Trigger Firing Order:
a. Enter a query.
b. Enter a nonexistent record.
c. Execute the query.

The two triggers listed above, the Enter Query triggers, and
the Execute Query triggers fire.


*************

Create Record 


1. Post-Change Block
2. When-Validate-Item Block
3. Post-Text-Item Block
4. When-Validate-Record Block
5. Post-Record Block
6. Post-Block Block
7. On-Savepoint Form
8. Pre-Commit Form
9. Pre-Insert Block
10. On-Insert Form
11. Post-Insert Block
12. Post-Forms-Commit Form
13. On-Commit Form
14. Post-Database-Commit Form
15. Pre-Block Block
16. Pre-Record Block
17. Pre-Text-Item Block
18. When-New-Item-Instance Form


*************

Update Record 


1. When-Database-Record Block
2. Post-Change Block
3. When-Validate-Item Block
4. Post-Text-Item Block
5. When-Validate-Record Block
6. Post-Record Block
7. Post-Block Block
8. On-Savepoint Form
9. Pre-Commit Form
10. Pre-Update Block
11. On-Update Block
12. Post-Update Block
13. Post-Forms-Commit Form
14. On-Commit Form

Here the transaction is complete and one record added.

15. Post-Database-Commit Form
16. Pre-Text-Item Block
17. When-New-Item-Instance Form

NOTE: To observe this Trigger Firing Order:

a. Execute a query.
b. Change a value.
c. Choose Action->Save from the menu.
d. Record the triggers from that point.


*************

Delete Record

1. On-Lock Block
2. When-Remove-Record Block
3. Post-Change Block
4. Post-Change Block
5. Post-Change Block
6. Post-Change Block
7. Post-Change Block
8. Post-Change Block
9. Post-Change Item
10. Post-Query Block
11. Post-Text-Item Block
12. Post-Record Block
13. Pre-Record Block
14. Pre-Text-Item Block
15. When-New-Record-Instance Block
16. When-New-Item-Instance Form

NOTE: To observe this Trigger Firing Order, delete a detail record.

Friday, July 18, 2014

Improve the performance of SQL*Loader

Can one improve the performance of SQL*Loader?
A very simple but easily overlooked hint is not to have any indexes and/or constraints (primary key) on your load tables during the load process. This will significantly slow down load times even with ROWS= set to a high value.
Add the following option in the command line: DIRECT=TRUE. This will effectively bypass most of the RDBMS processing. However, there are cases when you can't use direct load. Refer to chapter 8 on Oracle server Utilities manual.
Turn off database logging by specifying the UNRECOVERABLE option. This option can only be used with direct data loads.
Run multiple load jobs concurrently.

Thursday, July 17, 2014

How to invoke an Oracle apps form from a workflow notification

How to invoke an Oracle apps form from a workflow notification

Open Document functionality is a standard functionality within Oracle workflow. This functionality allows the user to go a particular transaction directly from the notification. The user gets to see a link in the workflow notification. On clicking this link he/she is directly taken to the Oracle form. The form opens and automatically queries the data for the user to view.


This functionality exists in seeded workflows. We can use this functionality within custom workflows to allow the users view the data directly in Apps from the notification.

We would like to show a particular GL journal to the user from our custom workflow. The journal is shown below.

Journal


We will check the Journal Header ID as this is the primary key that will be used to uniquely identify the data and will be used in querying the form once it opens from the notification.
Click on Help > Diagnostics > Examine
We get Header ID = 979869.
Step 1: Oracle Form check
Now we need to check the form name and the function name. Click on Help > Diagnostics > Custom Code > Personalize.
Note the Form and Function name. The Function name is GLXJEENT_A and the form name is GLXJEENT.
We have to check the parameters for the form so that we can pass the right values into it. To do so, we need to download the form down into our local computer so that we can open the form in Forms Builder to identify the parameters. We shall download the form,GLXJEENT.fmb, from $AU_TOP/forms/US directory on the server. After downloading and opening the form we shall open the Parametersection. It will look like the following,
We need to pass values into some of the form parameters displayed above. For this form we have to pass values into 3 parameters,
  • AUTOQUERY_LEVEL
  • AUTOQUERY_COORDINATION
  • AUTOQUERY_CRITERIA
Check the properties of each of the parameters
  • AUTOQUERY_LEVEL
  • AUTOQUERY_COORDINATION
  • AUTOQUERY_CRITERIA
From the properties of the parameters we will get to know what kind of values to pass.
Step 2: Develop the workflow
Develop a workflow in the Workflow Builder. This will be a very simple workflow that will send an approval message to an approver who will get the Form link in the notification. We have created our workflow type, Test Form from Workflow, and the Internal name isTESTFORM.
Main features of the workflow are,
  1. Attribute for storing the Journal Header id
  2. Attribute to store the Form link
  3. Attribute to store the approver number
  4. Approval message
  5. Approval notification
  6. Approval process
The workflow is shown below.
Check the attribute, View Journal form.
Note that the type of this attribute is Form. Also note the value. It is set to GLXJEENT_A:AUTOQUERY_LEVEL=”JOURNAL” AUTOQUERY_COORDINATION=”INITIAL” autoquery_criteria=”&JE_HEADER_ID”.
Important:
Format for invoking a form is,
<Function Name>:<Param1>=”&WF_ATTRIBUTE1″ <Param2>=”&WF_ATTRIBUTE 2″….
We need to pass the values of the form parameters into the form function as given above and workflow will identify the form from the function and invoke it from the notification.
Ensure that the View Journal Form attribute is attached to the workflow message along with the other attributes, Journal Header ID andApprover Number. The properties of the View Journal Form attribute on the message level is,
The message is set as
The workflow process is
After the development is done, save the workflow into the database.
Step 3: Test the workflow
Login to Oracle and go to Workflow Administrator responsibility. Then navigate to Developer Studio tab.
Enter the Workflow Type = Test Form from Workflow or the Internal Name as TESTFORM. Then click on Go button.
You will get to see the workflow now. Click on the Run icon. Now you will be taken to the workflow initiation screen. Enter the values forItem KeyJournal header ID and Approver Number fields as these values are essential to the workflow. The value for View Journal Form workflow attribute will be automatically populated from the workflow itself.
Point: We have passed the Journal Header ID for the journal that we had viewed at the beginning of this article so that we can verify the results.
Click on Submit button. You will get a confirmation message.
Click on OK. Then click on Status Monitor tab.
Enter the following on Status Monitor,
Type Internal Name: TESTFORM
Item Key: TEST10013
Click on Go
Click on Select and then Activity History. Now all the activities are shown and we see that workflow has sent the notification to the approver.
Click on the Notification icon.
Now the notification is displayed. You can now see the link, View Journal Form, on the bottom left of the screen.
Note:
The link name is always same as the attribute name.
Click on the link, View Journal Form.
Now the Oracle Apps form applet opens and we are prompted for a responsibility. Since we are about to view a Journal we need to select a General Ledger responsibility.
When we click on OK. The responsibility changes and the Journal form opens with the details of the Journal.
The link we created to the form is working perfectly. The same method can be used to invoke other seeded forms as well as custom forms.

Thursday, July 10, 2014

P2P Flow SQL Query Link

R12

/* Formatted on 7/10/2014 9:13:18 AM (QP5 v5.256.13226.35510) */
SELECT prh.segment1 "PO Requisition Number"
     , pha.segment1 "PO Number"
     , aps.SEGMENT1 "Supplier Number"
     , aps.vendor_name
     , apss.vendor_site_code
     , apsc.first_name
     , apsc.last_name
     , pla.item_id
     , plla.ship_to_organization_id
     , plla.ship_to_location_id
     , rt.transaction_type
     , rt.destination_type_code
     , rsh.receipt_num "PO Receipt Number"
     , aia.invoice_num
     , aida.dist_code_combination_id
     , aca.check_number
     , gjh.ledger_id
     , gjh.name
  FROM po_requisition_headers_all prh
     , po_requisition_lines_all prl
     , po_req_distributions_all prd
     , po_headers_all pha
     , po_lines_all pla
     , po_distributions_all pda
     , po_line_locations_all plla
     , ap_suppliers aps
     , ap_supplier_sites_all apss
     , ap_supplier_contacts apsc
     , rcv_transactions rt
     , rcv_shipment_headers rsh
     , rcv_shipment_lines rsl
     , ap_invoices_all aia
     , ap_invoice_lines_all aila
     , ap_invoice_distributions_all aida
     , ap_invoice_payments_all aipa
     , ap_checks_all aca
     , xla.xla_transaction_entities xte
     , xla_events xe
     , xla_ae_headers xah
     , xla_ae_lines xal
     , xla_distribution_links xdl
     , gl_import_references gir
     , gl_je_batches gjb
     , gl_je_headers gjh
     , gl_je_lines gjl
 WHERE prh.segment1 = :RequitionNumber --Right click :RequitionNumber from Toad Enable Prompt For Substitution Variables
   AND aps.vendor_id = pha.vendor_id
   AND apss.vendor_id = aps.vendor_id
   AND apss.vendor_site_id(+) = pha.vendor_site_id
   AND apss.vendor_site_id = aca.vendor_site_id
   AND apsc.vendor_site_id = apss.vendor_site_id
   AND apsc.vendor_contact_id = pha.vendor_contact_id
   AND prl.requisition_header_id = prh.requisition_header_id
   AND prd.requisition_line_id = prl.requisition_line_id
   AND pda.req_distribution_id = prd.distribution_id
   AND pla.po_header_id = pda.po_header_id
   AND pla.po_line_id = pda.po_line_id
   AND pha.po_header_id = pla.po_header_id
   AND pha.org_id = 204
   AND plla.po_header_id = pla.po_header_id
   AND plla.po_line_id = pla.po_line_id
   AND rt.transaction_type = 'DELIVER'
   AND rt.po_header_id = pha.po_header_id
   AND rt.po_line_id = pla.po_line_id
   AND rsh.shipment_header_id = rt.shipment_header_id
   AND rsl.shipment_header_id = rsh.shipment_header_id
   AND rsl.shipment_line_id = rt.shipment_line_id
   AND aila.po_header_id = pha.po_header_id
   AND aila.po_line_id = pla.po_line_id
   AND aia.invoice_id = aila.invoice_id
   AND aida.invoice_id = aila.invoice_id
   AND aida.invoice_line_number = aila.line_number
   AND aipa.invoice_id = aia.invoice_id
   AND aca.check_id = aipa.check_id
   AND xte.entity_code = 'AP_PAYMENTS'
   AND xte.transaction_number = aca.check_number
   AND xte.source_id_int_1 = aipa.check_id
   AND xte.security_id_int_1 = aia.org_id
   AND xe.entity_id = xte.entity_id
   AND xah.event_id = xe.event_id
   AND xal.ae_header_id = xah.ae_header_id
   AND xal.ae_line_num = aida.invoice_line_number
   AND xdl.ae_header_id = xah.ae_header_id
   AND xdl.ae_line_num = xal.ae_line_num
   AND xdl.applied_to_dist_id_num_1 = aida.invoice_distribution_id
   AND gir.reference_5 = xte.entity_id                            -- Entity Id
   AND gir.reference_6 = TO_CHAR (xe.event_id)                      --Event Id
   AND gir.reference_7 = TO_CHAR (xah.ae_header_id)            -- AE Header Id
   AND gir.gl_sl_link_id = xal.gl_sl_link_id
   --and gir.created_by = 1318
   AND gjb.je_batch_id = gir.je_batch_id
   AND gjh.je_batch_id = gjb.je_batch_id
   AND gjh.je_header_id = gir.je_header_id
   AND gjl.je_header_id = gjh.je_header_id

   AND gjl.je_line_num = gir.je_line_num

11i

/* Formatted on 7/10/2014 9:22:34 AM (QP5 v5.256.13226.35510) */
SELECT A.ORG_ID "ORG ID"
     , E.VENDOR_NAME "VENDOR NAME"
     , UPPER (E.VENDOR_TYPE_LOOKUP_CODE) "VENDOR TYPE"
     , F.VENDOR_SITE_CODE "VENDOR SITE"
     , F.ADDRESS_LINE1 "ADDRESS"
     , F.CITY "CITY"
     , F.COUNTRY "COUNTRY"
     , TO_CHAR (TRUNC (D.CREATION_DATE)) "PO DATE"
     , D.SEGMENT1 "PO NUMBER"
     , D.TYPE_LOOKUP_CODE "PO TYPE"
     , C.QUANTITY_ORDERED "QTY ORDERED"
     , C.QUANTITY_CANCELLED "QTY CANCALLED"
     , G.ITEM_DESCRIPTION "ITEM DESCRIPTION"
     , G.UNIT_PRICE "UNIT PRICE"
     ,   (NVL (C.QUANTITY_ORDERED, 0) - NVL (C.QUANTITY_CANCELLED, 0))
       * NVL (G.UNIT_PRICE, 0)
          "PO Line Amount"
     , (SELECT DECODE (PH.APPROVED_FLAG, 'Y', 'Approved')
          FROM PO.PO_HEADERS_ALL PH
         WHERE PH.PO_HEADER_ID = D.PO_HEADER_ID)
          "PO STATUS"
     , A.INVOICE_TYPE_LOOKUP_CODE "INVOICE TYPE"
     , A.INVOICE_AMOUNT "INVOICE AMOUNT"
     , TO_CHAR (TRUNC (A.INVOICE_DATE)) "INVOICE DATE"
     , A.INVOICE_NUM "INVOICE NUMBER"
     , (SELECT DECODE (X.MATCH_STATUS_FLAG, 'A', 'Approved')
          FROM AP.AP_INVOICE_DISTRIBUTIONS_ALL X
         WHERE X.INVOICE_DISTRIBUTION_ID = B.INVOICE_DISTRIBUTION_ID)
          "Invoice Approved?"
     , A.AMOUNT_PAID
     , H.AMOUNT
     , I.CHECK_NUMBER "CHEQUE NUMBER"
     , TO_CHAR (TRUNC (I.CHECK_DATE)) "PAYMENT DATE"
  FROM AP.AP_INVOICES_ALL A
     , AP.AP_INVOICE_DISTRIBUTIONS_ALL B
     , PO.PO_DISTRIBUTIONS_ALL C
     , PO.PO_HEADERS_ALL D
     , PO.PO_VENDORS E
     , PO.PO_VENDOR_SITES_ALL F
     , PO.PO_LINES_ALL G
     , AP.AP_INVOICE_PAYMENTS_ALL H
     , AP.AP_CHECKS_ALL I
 WHERE A.INVOICE_ID = B.INVOICE_ID
   AND B.PO_DISTRIBUTION_ID = C.PO_DISTRIBUTION_ID(+)
   AND C.PO_HEADER_ID = D.PO_HEADER_ID(+)
   AND E.VENDOR_ID(+) = D.VENDOR_ID
   AND F.VENDOR_SITE_ID(+) = D.VENDOR_SITE_ID
   AND D.PO_HEADER_ID = G.PO_HEADER_ID
   AND C.PO_LINE_ID = G.PO_LINE_ID
   AND A.INVOICE_ID = H.INVOICE_ID
   AND H.CHECK_ID = I.CHECK_ID
   AND F.VENDOR_SITE_ID = I.VENDOR_SITE_ID
   AND C.PO_HEADER_ID IS NOT NULL
   AND A.PAYMENT_STATUS_FLAG = 'Y'
   AND D.TYPE_LOOKUP_CODE != 'BLANKET';