Search

OracleDollars

Showing posts with label Technicals. Show all posts
Showing posts with label Technicals. Show all posts

How to deal with AP/AR Netting related issues


Download PDF

The first and foremost step to ensure that the netting process does not error out is to check the following pre-requisites.

  1. Ensure that all the setups pertaining to Netting are in place.
    Please see: http://oracledollarschennai.blogspot.com/2008/10/apar-netting.html

  1. Ensure that all the packages related to FUN% are Valid and none are in Invalid Status. Once can use the below mentioned SQL to identify the netting related Invalid objects:

    SELECT object_name, object_type, owner, status
    FROM dba_objects
    WHERE status = 'INVALID'
    AND object_name LIKE 'FUN%'’

There are a few known issues with Netting. The error is normally encountered while submitting the “Create Netting Batch” process or while running the “Submit Netting Batch” concurrent program.

Once either of these concurrent program errors out, check the log file from the Submit Concurrent Program window. Normally, the log file will give a generic message as ‘Unable to Create AR Receipt’ or ‘Error applying a Receipt’.

The cause of the issue will be normally based on some wrong setups or some invalid value passed via the Netting Agreement.

Step 1:
======

The first step in the process of identifying the issue is by getting the debug log file. The debug messages from Netting will give a clear cut idea as of which place the program fails. Once the debug file is reviewed, the cause of the issue will normally be quite clear.

Please see: http://oracledollarschennai.blogspot.com/2009/04/download-pdf-how-to-debug-oracle.html

If the debug file does not give much information (Normally, the debug file will give the actual error), then resort to the second step.

Step 2:
======

The second step in debugging the issue is to get the version of the file ‘FUNNTTXB.pls’.
You can use the below mentioned command to get the version of the file.

cd $FUN_TOP/patch/115/sql
Strings –a ‘FUNNTTXB.pls’ |grep ‘$Header’

Ensure that this file is on the current highest version available via metalink. Apply the patch to get to the latest version if you are not at the highest level.

If a Netting Batch is stuck in Error, it is normally not possible to change the status, in such cases, you can resort to a datafix by deleting the netting batch from the Backend.

Please see: http://oracledollarschennai.blogspot.com/2008/12/deleting-netting-batch-from-backend.html

Step 3:
======

Another issue which normally happens with Netting is the creation of another Receipt Method, AP/AR Netting(1) by the application of some of the Netting related Patches. This can be fixed with the help of a Datafix.

Please see the steps mentioned below to perform a Datafix once you are able to identify the existence of another Receipt method ‘AP/AR Netting(1)’.

By default, the Receipt method for Netting is ‘AP/AR Netting’ and the id associated with it is ‘-1’. The below mentioned datafix will remove the ‘AP/AR Netting(1)’ and will replace the id of ‘AP/AR Netting’ as –1. Also, it will remove the reference of ‘AP/AR Netting(1)’ from the dependent tables.

The datafix is as below:

--Backup

CREATE TABLE receipt_class_bkp2 AS
SELECT *
FROM ar_receipt_classes
WHERE receipt_class_id = -1;


CREATE TABLE receipt_method_bkp2 AS
SELECT *
FROM ar_receipt_methods
WHERE receipt_method_id = -1;

CREATE TABLE rec_method_acct_bkp2 AS
SELECT *
FROM ar_receipt_method_accounts_all
WHERE receipt_method_id = -1

--Delete

DELETE FROM ar_receipt_classes
WHERE receipt_class_id = -1;

DELETE FROM ar_receipt_methods
WHERE receipt_method_id = -1;

DELETE FROM ar_receipt_method_accounts_all
WHERE receipt_method_id = -1;

COMMIT;

--Update

UPDATE ar_receipt_methods
SET name = 'AP/AR Netting',
receipt_method_id = -1,
receipt_class_id = -1
WHERE receipt_method_id = 1;

UPDATE ar_receipt_method_accounts_all
SET receipt_method_id = -1
WHERE receipt_method_id = 1;

UPDATE ar_receipt_classes
SET receipt_class_id = -1
WHERE receipt_class_id = 1

COMMIT;

This will ensure that you do not have any occurrence of ‘AP/AR Netting(1)’ in the instance.
Now, the next step is to identify any receipt with the ‘AP/AR Netting(1)’ in the receipt tables.
You can use the below mentioned query to identify the same.

SELECT cash_receipt_id,
receipt_number
FROM ar_cash_receipts_all
WHERE receipt_method_id = 1;

If this returns any rows, then probably the receipt will have Receipt Method as ‘AP/AR Netting(1)’.

In order to rectify this receipt, perform the below mentioned datafix.

--Backup

CREATE TABLE bkup_tbl_cr_method AS
SELECT *
FROM ar_cash_receipts_all
WHERE cash_receipt_id IN
(SELECT cash_receipt_id
FROM ar_cash_receipts_all
WHERE receipt_method_id = 1);

--Update

UPDATE ar_cash_receipts_all
SET receipt_method_id = -1
WHERE cash_receipt_id IN
(SELECT cash_receipt_id
FROM ar_cash_receipts_all
WHERE receipt_method_id = 1);

COMMIT;

This should rectify all the receipts.

Most of the issues with Netting will get resolved once the above steps are followed. If you are still not able to resolve the issue, then log an SR with Oracle Support.

More on this to follow in my coming posts.

How to Debug Oracle Applications:




There are three major ways in which one can debug the Oracle Applications. This is applicable to all the released versions in Oracle. Let me give a brief on how to proceed with each of them.

Pre-Requisites:

- You must have the backend access to database and the Unix Box.

- Must be well versed with SQL and PL/SQL

- Must have a good idea about the functional flow of the Applications.

- Access to System Administrator Responsibility in Oracle Applications.

Lets begin with the methods. As already mentioned, there are three ways of debugging the Applications and they are:

  1. Debug Log
  2. Trace and TkProf
  3. FRD Log


Lets discuss the ways in which this can be obtained and how to read them.

Debug Log Messages:

This is one of the most commonly used debug methods. This gives a fair idea of the application as of which package is failing and which value is not getting passed to which parameter and so on.. more importantly, the backend data flow.

Step 1:

========

The first and foremost thing in this process is to enable the debug messages. This can be achieved by setting the following Profile Options at the User Level.

Please note that you can set the profile options only if you have the access to “System Administrator Responsibility”.

FND: Debug Log Enabled YES -- Enables Debugging messages.

FND: Debug Log Filename NULL -- To store the file in an external file, if NULL,

the values are written in a table

FND: Debug Log Level STATEMENT -- Most detailed log

FND: Debug Log Module % -- Application specific, if %, it is enabled for all

applications, else values can be ‘ar%’, ‘ap%’

Step 2:

======

Once the Profile options are set, the next step is to find the initial value from where our debugging routine will start. To identify this value, you will have to login to the Database by using SQL Developer/TOAD and then execute the following Query:

SELECT MAX(LOG_SEQUENCE)
FROM FND_LOG_MESSAGES

This will give a value. Keep this value for future references.

Step 3:

======

Now, try to reproduce the issue and ensure that you try to stay on track in reproducing the issue and leave out extraneous steps so that you don't end up with debug messages that are not relevant to your issue. It is ideal to not have anyone else using the Responsibility you have enabled debug for, so that only messages pertaining to your testcase are picked up.

Step 4:

======

Once the issue is reproduced, stop at the step next to the error, like Click OK to the error and then the next step is to ensure that you retrieve the debug log messages generated by your test case. To retrieve the messages, execute the below query in SQL Developer/TOAD.

SELECT MESSAGE_TEXT, MODULE
FROM FND_LOG_MESSAGES
WHERE LOG_SEQUENCE > &max_log_from_step2
ORDER BY LOG_SEQUENCE;

Now, spool this file to an excel sheet and save it in your system.

Step 5:

======

The next step in the process is to read the retrieved messages. Here is how you can interpret the messages generated.

Here is how a sample debug file looks like:

create_person (+)

LoadDataSources (+)

cacheSetupForOtherEntities (+)

G_DATASOURCE_LOADED = N

l_str = 'USER_ENTERED'

l_str = 'USER_ENTERED'

l_str = 'USER_ENTERED'

l_str = 'USER_ENTERED'

l_str = 'USER_ENTERED'

l_start = 5

i = 1

l_entity_name = 'HZ_PERSON_PROFILES'

l_entity_id = -1

i_content_source_type.COUNT = 0

l_str =

i = 2

l_entity_name = 'HZ_ORGANIZATION_PROFILES'

l_entity_id = -2

i_content_source_type.COUNT = 1

l_str = 'USER_ENTERED'

total = 7

cacheSetupForOtherEntities (-)

p_mixnmatch_enabled = N

p_selected_datasources = 'USER_ENTERED'

LoadDataSources (-)

do_create_party (+)

validate_person (+)

first_name or last_name is mandatory. x_return_status = S

head_of_household_flag in lookup YES/NO. x_return_status = S

deceased_flag in lookup YES/NO. x_return_status = S

after validating date_of_birth and date_of_death against SYSDATE x_return_status = S

(+) after validating the date_of_death and date_of_birth... x_return_status = S

created_by_module is madatory field. x_return_status = S

validate_person (-)

l_mixnmatch_enabled = N

l_selected_datasources = 'USER_ENTERED'

do_create_update_party_only (+)

do_create_party_name (+)

l_party_name = ALLY TIONG

do_create_party_name (-)

Generated person key : TNG.ALC

validate_party (+)

validate_party (-)

hz_parties_pkg.Insert_Row (+)

hz_parties_pkg.Insert_Row (-)

do_create_update_party_only (-)

do_create_party_profile (+)

do_create_person_profile (+)

hz_person_profiles_pkg.Insert_Row (+)

do_create_person_name (+)

do_create_person_name (-)

l_person_name = ALLY TIONG

hz_person_profiles_pkg.Insert_Row (-) x_profile_id = 2783499

do_create_person_profile (-)

do_create_party_profile (-)

do_process_classification (+)

party_id =

do_process_classification (-)

Event Name:oracle.apps.ar.hz.Person.create Event Key:oracle.apps.ar.hz.Person.create382123Maximum nested raise count:100Nested raise count: 0

For every ‘(+)’, the control is getting into that Package and for every “(-)”, the control is coming out of that package. It also depends on what kind of debugging messages are coded in those packages where the control enters and processes the code and then passes to the next level.

P.S: Almost all the packages in Oracle Applications, has debugging messages enabled, however, there are exceptions, where packages may not have debugging enabled, hence, will not be shown in the debug file.

To find the cause of the issue, the first thing to find in a debug file, is the word ‘Exception’. This will be showing the package name where the error occurs. Just, open the package in SQL Developer/TOAD and see the SQL being fired.

Check for the values which are being passed to this SQL and see the exception block of the script. On analyzing further, you will mostly be able to find the value which is not getting passed or the wrong value being passed to this SQL and the reason for the error.

Once this is identified, you have to check the Application Settings and modify it accordingly to have the correct value to be passed to the SQL to prevent it from erroring out.

I will be posting the other two debugging methods in my coming posts.

Deleting a Netting batch from backend


Whenever there is an issue with Netting Batch where the batch is in error and the user is unable to Update or Delete the Netting batch, one can use the following SQL Statements to delete the Batch from the Backend.

1. Select CHECKRUN_ID, Batch_id from Fun_net_batches_all where Batch_Name = '&Your_batch_name'

2. Delete from fun_net_batches_all where Batch_Name = '&Your_batch_name'

3. Delete from FUN_NET_AR_TXNS_ALL where Batch_id= &Batch_id_from_step1

4. Delete from FUN_NET_AP_INVS_ALL where Batch_id= &Batch_id_from_step1

5. To remove the transactions from AP that was picked up in the Netting Batch, you may please run the following script.

select * from AP_PAYMENT_SCHEDULES_ALL where checkrun_id= &Checkrun_Id_from_step1;

If this returns any rows, then use the below statement, else no action is required

UPDATE AP_PAYMENT_SCHEDULES_ALL
SET checkrun_id = NULL
WHERE invoice_id =&invoice_id_from_prev_sel_stmnt and
checkrun_id=&Checkrun_Id_from_step1;

Once this is done, then issue a COMMIT.

Forms Personalization and Custom.PLL


What is this?

Oracle Supplied forms are the seeded forms and have a standard functionality attached to them. Whenever there is a need to change the functionality or change the look and feel of the forms, we use Forms Personalization or Custom.PLL.

Custom.PLL or Forms personalization is used to alter the standard functionality of an Oracle Seeded form without affecting the base form and without altering its coding. In older versions, prior to 11i, Custom.PLL was most prominently used for adding additional features in the seeded form but the latest version of Oracle EBS comes with the feature called as Forms Personalization which allows even an end user to alter the seeded forms functionality using an user interface called the Personalization form.


Advantages of Forms Personalization over Custom.PLL

Forms personalization can be used by an user with limited PL/SQL knowledge.
Changes take place immediately on reopening the form.
Anything which can be done using Custom.PLL can be done using Forms Personalization also.
Personalizations are stored in base tables related to Form Personalization.


Restrictions of Custom.PLL and Forms Personalization:

It is not possible to create any new item in the Standard form using Custom.PLL or Forms Personalization.


How to

Normally a user with some basic knowledge of Oracle Forms and PL/SQL is allowed to modify a standard form. This can be achieved by setting the profile Option

FND: Diagnostics (Set to Yes at User Level)
Hide Diagnostics (Set to NO by default)

This enables the diagnostics menu when the particular user logs in and provides access to the personalization form. Once the form is open, the user can make any modifications for the specific form and then save and check the effect.
Custom.PLL is mainly used by the developers who have a vast knowledge of PL/SQL and can attach any logic using PL/SQL which in-turn will implement the business logic when the form opens. To achieve this, the developer has to first edit Custom.PLL and then add the code in it, compile and save it in the UNIX box and then deploy it in the applications. The changes will be reflected only the next time when the application is restarted.


Some typical uses


  • Changing the property of an Item. It can be any property associated with the item.
  • Calling a different form and passing a value from the calling form to the called form.
  • Addition of special menus apart from the standard menu.
  • Displaying custom messages for debugging purposes.

Feel free to post your comments and your queries.


Enabling Descriptive Flexfield in Oracle Applications


Summary:
The key for enabling a Descriptive Flexfield is to identify the Base table of the related form and then use the table name to query the Descriptive Flexfield Title. Once the title of the Descriptive Flexfield is obtained, then we just have to Query the name in the Application Developer responsibility and then add the desired columns. This will enable the Descriptive Flexfield.

Getting Started:
Lets enable the Descriptive Flexfield of Purchase Order form. The initial screen looks as shown below and the DFF field is Disabled.



Get the name of the view from which this form is created using the Tools=>Record History option




Use the utility TOAD to find the base table of this view. We will find that the base table involved here is PO_HEADERS_ALL.

Now, switch to Application Developer Responsibility and open the form for registering the Flexfields.

Navigation:

Application Developer => Flexfields => Descriptive => Register

The window which opens is as shown below:





Now, query this form by providing the values for Application as ‘Purchasing’ and the Table Name as ‘PO_HEADERS_ALL’. The result will be as shown below:



Once the window is queried, then select the Title ‘PO Headers’ from this window and then navigate to
Application Developer => Flexfield=> Descriptive => Segments



Now, query this window using the title and the application name. The window is as shown below:




Now, uncheck the freeze flexfield definition and then add the context field values as per the need. This is illustrated in the screen below.





Here, I have added A and B as the code and ‘Global Data Elements’ is default and is always enabled.

Now, select the code and then add columns to it. It is shown as below



When clicked on Segments, we will get the window as below. We then specify the columns which will get displayed when this code is selected.



If desired, we can attach the value set also to restrict the user from entering any garbage value.

Now, save this and follow the same steps for enabling the other code(B) also and also ensure that to show the difference between code A and code B, enable three columns in Code B.

Now, the last step is to specify a default value to the Context Field. I am providing here a reference field as TYPE_LOOKUP_CODE. Ensure that the checkboxes are checked. The screen is as below.



Once this is done, we then have to compile the flexfield and save the window. For compiling the Flexfield definition, we need to first save the window and then check the freeze flexfield checkbox and then click on Compile.



Now, Login to Purchasing responsibility and then open the Purchase Order form.



This window shows that the DFF field is now enabled. When we click on the DFF window, we will be getting a screen as below



When the LOV is clicked, we get the values populated by the reference column which we gave as ‘TYPE_LOOKUP_CODE'.It is shown below




Now, based on the value selected we will get the corresponding columns which is shown in the subsequent screen.



Hence, this is how a flexfield works. When the data is saved, it will be saved in the base table on the corresponding Attribute columns as specified in the Application developer responsibility.

Your comments and queries are always appreciated.




Flexfields in Oracle Applications


What is a Flexfield?
As the name suggests, a Flexfield is a ‘flexible field’. A flexfield is a field made up of segments. Segments are nothing but columns of the base table. Each segment has a name that can be assigned and a set of valid values. There are two types of Flexfields in Oracle Applications and they are called as
• Key Flexfield
• Descriptive Flexfield
With both of these flexfields, users get the ability to customize their application to match their business needs without programming.


When and where are these flexfields used?
Descriptive Flexfields are used in places whenever the user feels a need of extra information apart from the Oracle supplied standard information in the forms.
Key Flexfields are used whenever there is a need for storing Key information related to the organization.

What is the difference between Key and Descriptive flexfields?

  • Key flexfield is used to store the key information about an organization whereas Descriptive flexfields are used to store any additional related information.
  • Key Flexfield values are stored in Segment columns in the base table whereas descriptive flexfield values are stored in the Attribute columns of the base table.
  • Key Flexfields are non-updatable and mostly have only restricted values as input (Attached Value sets) wheras a the fields in Descriptive Flexfield are updatable.
  • Key flexfields do not have any context sensitive segments whereas Descriptive flexfields can be made into context sensitive fields.
  • Key Flexfields are the mandatory fields whereas descriptive flexfields are not mandatory by default but can be made mandatory.

What are the Base Tables involved in Flexfields creation?
The tables involved are
FND_FLEX_VALUES_TL, FND_ID_FLEXS, FND_FLEX_VALUES, FND_FLEX_VALUE_SETS, FND_ID_FLEX_STRUCTURES

Query to find the number of oracle Supplied key flexfields in each application

SELECT fa.application_name application, COUNT (fif.application_id) flexfield_count
FROM fnd_id_flexs fif, fnd_application_tl fa
WHERE fif.application_id = fa.application_id
GROUP BY fa.application_name

A sample output of this query is as below:

These were some of the basics involved with Flexfields in Oracle Applications. The next post will be on how to enable a Descriptive Flexfield in Oracle Applications.

Please feel free to post your comments or queries




Basics in Bulk Binding

What is the need for Using Bulk Binding concepts in programs?

To answer this question, we must first understand how a data is fetched in a PL/SQL program. Every program which fetches data uses SQL at the back end, hence the need for a SQL engine to fetch data’s. Whenever a PL/SQL block calls a SQL statement, the control passes to SQL engine, this in-turn fetches the data from the database and transfers the data and the control back to PL/SQL engine for further processing.

If we code a program which uses a lot of data fetching and loops, then it causes a lot of Context Switching between PL/SQL and SQL engines, thereby decreasing the performance considerably. It is here where Bulk Binding comes in handy. When we use Bulk Binding concepts in our programs, it eliminates the multiple context switching between the two engines and considerably increases the performance of the program.

How Bulk Binding works?

As discussed earlier, Bulk Binding reduces the context switching between PL/SQL and SQL engines in a very simple manner. Here is how it achieves this:
Lets take a normal cursor which has a set of rows and we would like to manipulate the data’s fetched from this cursor in our program. This obviously needs a lot of context switching when we use a Cursor For Loop, but when we incorporate Bulk binding in the program, what it does is, it will fetch all the data’s from the database and store it in a temporary table in PL/SQL (The temporary table can be a VARRAY, PL/SQL TABLE, RECORD TYPE, %ROWTYPE, CURSOR TYPE). Once it is stored in these temporary tables, then we just need to use these tables to manipulate further in our programs as the data is now in PL/SQL engine. This eliminates a lot of context switching when a large data is concerned.

What are the types of Bulk Binding?

With SELECT or FETCH statements
BULK COLLECT INTO clause

In-Bind binding. (INSERT or UPDATE)
FORALL Clause

Out-Bind binding.
RETURNING clause

What are the attributes of Bulk Binding?

The main attribute of bulk Binding is SQL%BULK_ROWCOUNT(i)
This gives the number of rows affected when using a Bulk Binding concept.
The other attributes are associated with error handling. They are
SQL%BULK_EXCEPTIONS(i).ERROR_INDEX
SQL%BULK_EXCEPTIONS(i).ERROR_CODE

What are the typical usage of Bulk Binding?

There are two important places where we can use Bulk Binding and they are discussed as below:

In a SELECT or FETCH statement. Whenever we need to fetch data’s from the database we need to use the BULK COLLECT INTO clause, hence this comes in handy in the SELECT and the FETCH statements.

While manipulating, DELETING, UPDATING or INSERTING. Whenever there is a data manipulation in bulk amounts, we can use the FORALL option. It performs all the manipulation at one go.

What are the limitations in Bulk Binding?

Bulk binding also has its share of limitations and some of them are

a) FORALL clause must precede only a DML statement.
b) Cannot use the DBMS_OUTPUT statement after FORALL clause.

Is there a way to limit the data that is inserted using the Bulk Binding concept?

Yes, there is a way in which you can restrict the number of rows to be fetched in a BULK COLLECT. What you can do is, you can specify the LIMIT clause followed by any number. BULK COLLECT will fetch only those many records which satisfies the number following the LIMIT Clause.

Example: FETCH cursor_name BULK COLLECT INTO collections_name LIMIT x;

Here x stands for a numeric value restricting BULK COLLECT records.

What is the use of SAVE EXCPTIONS in Bulk Binding?

Whenever a PL/SQL program encounters the keyword SAVE EXCEPTIONS after a FORALL clause, it saves the exception in the SQL%BULK_EXCEPTIONS collection and does not interrupt the operation.
To explain in detail, lets say we are manipulating a thousand records, FORALL clause encounters an error in the 500th record, if SAVE EXCEPTIONS clause is not specified, then the operation gets interrupted causing a ROLLBACK of the entire operation and when SAVE EXCEPTIONS is specified then the exception which gets encountered midway through the operation is stored in the collection of errors called as BULK_EXCEPTION and the operation continues without interruption. Later we can view the exceptions caused in the operation by querying the error collection using SQL%BULK_EXCEPTIONS(i).ERROR_INDEX and SQL%BULK_EXCEPTIONS(i).ERROR_CODE.

What are the possible errors that may occur while using BULK BINDING?

The only error I can foresee getting with FORALL is this one:
ORA-22160: Element at index does not exist
And you will only get that if you are somehow binding to an index that does not exist.You may also get complaints if you use the index in an expression, which is not supported:
PLS-00430: FORALL iteration variable i is not allowed in this context

Now, lets see some of the sample programs using BULK BINDING concepts.

Sample BULK COLLECT program:

DECLARE
TYPE Cust_tab IS TABLE OF Customers_Active%ROWTYPE;
Custs Cust_tab;
BEGIN
SELECT Customer_Account_Id, Effective_Date, Expired_Date
BULK COLLECT INTO Custs

FROM Customers_Active
WHERE Effective_date BETWEEN
TO_DATE(’01-JAN-2004’ , ‘DD-MON-RRRR’) AND TRUNC(SYSDATE);
END;


Sample FORALL Program:

DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10,30,70);
BEGIN
FORALL i IN depts.FIRST..depts.LAST
UPDATE emp SET sal = sal + 100 WHERE deptno = depts(i);
END;

So this should probably give you some insight on the basic concepts of BULK BINDING.
Feel free to post your comments and queries in the comments section.

A brief about Procure to Pay cycles

Procure to Pay cyle:

The basic P2P (Procure to Pay) Cycle can be explained as:

The first step in this is to gather the requisition from various modules using the ‘Requisition Import ‘ concurrent program. For example, when we run a
min-max planning in inventory, we get the list of items which is below the reorder level. In the same report there is an option to create requisition as well. When that option is enabled, the system internally creates a requisition for that particular item which is below the reorder level. This requisition can be viewed in Purchasing responsibility. Note the Requisition number and then create an RFQ (Request For Quotation) using this Requisition as the reference. Once this RFQ is created, it is sent to the various suppliers. Once the suppliers receive these quotations, they then send their bid/quotation for approval. Then the Buyers sit and analyze these quotations and finally zero in on a particular quotation which is approved as it satisfies the various conditions. When this quotation is approved, it is then converted to a Purchase Document (there are four types of Purchase Documents). After the creation of Purchase documents, it is then approved following the approval hierarchy. Once this Purchase order is approved, it is then sent to the supplier who in-turn ships the materials to the location specified in the PO Document. Once the material is shipped, it is then transferred to the sub-inventory as per the rule set in Receiving Controls of the particular Purchase document. Once the material is received then the next step is to process the payment for the received materials. For doing this, an Invoice is created and this invoice is sent to the Payables department which pays the supplier based on the purchase Order. Finally, the transaction is posted to General Ledger.

Lets discuss the tables that gets affected while performing a Procure to Pay full cycle:

















Hence, this summarises the technical aspect of Procure to Pay cycle.