Oracle eBusiness Suite

April 29, 2008

Managing Lifecycle of an Item using API

Here is the code snippet for creating items using API (traditionally we are used to use item open interface) in the Product Life Cycle Management process. While this does not replace loading items using open interface, this API can be used to manage the lifecycle of the item on a dialy basis.

Over a period time, companies conceptualize products, design them, build them, manage them and finally, retire them.

Here in the article I am introducing the API first. In the subsequent articles, we will manage the “lifecycle” of the product using the same API.

These code snippets are tested in 12.0.4.

Here is the code.

April 28, 2008

Bringing in a PDF file as an attachment to an entity using APIs

Attachments in Oracle eBusiness Suite provide a great functionality to attach a file of type, text, word, excel or pdf against a specific entity. This entity can be an Item or BOM. For that matter attachments can be created for any entity be it master or transactional data. And from the very screen where this data is seen  attachments are available to view as file.

A number of times when we are bringing this data from either other applications or converting data from the legacy systems, we need to load attachments against that entity. A classic example is to load a PDF file (instruction manual) that gives you a lot of information about an item. Or an assembly diagram of the product against its BOM is also a good example.

This article provides a way on how to bring in an attachment along with that entity.

In this example I will be creating an item using an API first and then attach a PDF file to that item. This article assumes some level of understanding of attachments functionality. Here are few steps in enabling attachments against an entity.

  1. Register document entities. Here you need to know what is the primary key of this document entity. In this example it is inventory_item_id and organization_id and document entity is MTL_SYSTEM_ITEMS (The table behind the items).
  2. Enable the attachments for a form or a function where you want attachment to be seen. As we have chosen item master, we need to find out the form function of the item master. You can find that from the menu.
  3. If there are many blocks in the form you need to know in which block you want this attachment to be seen. Choose that block.
  4. If you have any security like Operating Unit, enable that as well.
  5. Make sure to choose the primary keys of the document entity in the entity declaration. In this case if you have chose Key1 for organization_id, the value of organization_id from the item master form will be stored in the pk1_value field and so on.
  6. Assign attachment categories to form functions. This decides what kind of document cartegories need to be assigned to form functions.

I have used  Vision instance to perform this test (12.0.4). I loaded this item into V1 (master organization of Vision Operations). To load item I have used Engineering API ego_item_pub.process_item.

Here are the steps involved:

First create a directory where you want the file to come and sit. If your partner system is sending the files everyday along with the data, you need to decide where to store that data on the server. Data file should contain the entity name (item number) and file name (file to be attached). File will come and sit on the server along with the data file. From here you can start loading into a staging table and process them.

Step 1:

Decide the location where the file is going to sit and create that directory using this script. In this example I am using  /tmp as my directory. Code is here.

Step 2:

Now we need to read this file in this directory and load that into a table. For that purpose I have created this table. Code is here.

Step 3:

Now load the file into this table. Code is here.

Step 4:

Now that we have file in the staging table, we will start loading the file into FND schema of Oracle Applications using this code.

Step 5:

Now let us use item API to load item and get the item_id. Use this code.

Step 6:

Use this inventory_item_id, organization_Id, x_access_id and x_file_id to load PDF file against this item. Use this code.

Now you should be able to see this attachment in the item master against this item TEST111 which is created.

 

October 23, 2007

Importing Sales Orders from Excel

This article gives you simple steps to load large sales orders in Order Management using Excel Spreasheet.

We arrived at this solution using some good features available in Oracle Database and Oracle Applications. Here are the steps.

  1. We create order header only (using sales order form) with all the necessary information like customer, order type, price list, sales person, sales credits, warehouse and the other values as deemed necessary.
  2. Now we create line information in Excel worksheet (a template is created). We enter values for the fields like Item, quantity, price list name (if that is different from header), Line Type, Sales Person (different from header), any DFF segments, Shipping Instructions if any, warehouse name so on. We can have as many fields as that can fit in the order lines table. But instead of entering all the values, we use defaulting rules to default a lot of values from the header.
  3. In this worksheet there is a simple marco written that we use to generate another worksheet in the same file for the entered rows.This macro does some basic validations on the information entered in the worksheet and generates the worksheet with this statement for each row.
    1.  
      •  insert into custom_lines_load_tbl  (column1,column2,….) values ( field1,field2,……)
  4. Now using these rows with this statement (generated worksheet) we create a simple text file (copy and paste).
  5. As a next step we upload this file as an attachment to the order header that we have created in the step number 1.
  6. Now we run a custom program to create order lines into this order. This program takes order number as a parameter. This program reads the file contents line by line and executes the insert statements. This is the heart of the solution which is to read the contents of the file which is stored as LOB and executing the statements. After all the insert statements are executed successfully, the program calls oe_order_pub API to create order lines.
  7. As you can see the program uses this feature : reading the file which is stored in the database as LOB line by line. Here is the code snippet to read the attached file stored as a file.

PROCEDURE parse_and_load_file (
      ERROR_CODE       OUT      VARCHAR2,
      retcode          OUT      NUMBER,
      p_order_number   IN       NUMBER
   )
   IS
      fil             BLOB;
      pos             INTEGER         := 0;
      amt             BINARY_INTEGER  := 32767;
      buf             RAW (2000);
      l_start         RAW (3000);
      l_end           RAW (3000);
      l_start_pos     INTEGER;
      l_length        INTEGER;
      nth             INTEGER         := 1;
      i               INTEGER         := 2;
      l_text          VARCHAR2 (4000);
      l_end_pos       INTEGER;
      l_plsql_block   VARCHAR2 (4000);
      k               INTEGER;
      l_write_buff    RAW (2000);
      l_text1         VARCHAR2 (4000);
      x_errbuf        VARCHAR2 (4000);
      x_retcode       NUMBER;
   BEGIN
      BEGIN
    begin
    delete custom_lines_upload_tbl
    where order_number=p_order_number
    and line_Id is null; –this is to make sure we do not load duplicate data
    exception when others then
    null;
    end;

SELECT file_data
  INTO fil
  FROM fnd_lobs
 WHERE file_id =
          (SELECT media_id
             FROM fnd_documents_vl
            WHERE document_id IN (
                     SELECT a.document_id
                       FROM fnd_attached_documents a, fnd_documents b
                      WHERE a.document_id = b.document_id
                        AND b.category_id =
                                     (SELECT category_id
                                        FROM fnd_document_categories_tl
                                       WHERE user_name = ‘Custom Lines Upload’)
                        AND entity_name = ‘OE_ORDER_HEADERS’
                        AND pk1_value = (SELECT header_id
                                           FROM oe_order_headers_all
                                          WHERE order_number = p_order_number)))
         FOR UPDATE;
      EXCEPTION
         WHEN OTHERS
         THEN
            debug_log
               (   ‘Order :’
                || p_order_number
                || ‘ does not have any file attached to it to load. Please attach the file and then try running this program’
               );
      END;

      k := DBMS_LOB.ISOPEN (fil);

      — debug_log(‘Checking whether the file is already open’);
      IF k = 1
      THEN
         –debug_log(‘file is already open. Closing it’);
         DBMS_LOB.CLOSE (fil);
      END IF;

      BEGIN
         –debug_log(‘Opening the file’);
         DBMS_LOB.OPEN (fil, DBMS_LOB.lob_readonly);
         k := DBMS_LOB.ISOPEN (fil);
      EXCEPTION
         WHEN OTHERS
         THEN
            debug_log
                    (‘Exception occured in checking whether the file is open’);
      END;

      IF k = 1
      THEN
         LOOP
            l_start := UTL_RAW.cast_to_raw (‘insert’);
            l_end := UTL_RAW.cast_to_raw (‘;’);
            l_start_pos := DBMS_LOB.INSTR (fil, l_start, 1, nth);
            pos := DBMS_LOB.INSTR (fil, l_end, 1, nth);
            buf := ”;
            –debug_log(‘Start position is :’||l_start_pos);
            –debug_log(‘End position is :’||pos);
            l_end_pos := (pos + 1) – (l_start_pos);
            –debug_log(‘Length of the string is :’||l_end_pos);
            –debug_log(‘Reading the file’);
            DBMS_LOB.READ (fil, l_end_pos, l_start_pos, buf);
            l_text := UTL_RAW.cast_to_varchar2 (buf);
            l_plsql_block :=
                  ‘begin’
               || fnd_global.NEWLINE ()
               || l_text
               || fnd_global.NEWLINE ()
               || ‘commit;’
               || fnd_global.NEWLINE ()
               || ‘exception when others then’
               || fnd_global.NEWLINE ()
               ||
                  –‘debug_log(”Exception occured in processing the line”);’||fnd_global.NewLine()||
                  ‘NULL;’
               || fnd_global.NEWLINE ()
               || ‘end;’;

            –debug_log(‘———————————————–‘);
            –debug_log(l_plsql_block);
            –debug_log(‘———————————————–‘);
            BEGIN
            –Now execute the dynamic pl/sql block to insert rows into custom table from the file
               EXECUTE IMMEDIATE l_plsql_block;
            EXCEPTION
               WHEN OTHERS
               THEN
                  –debug_log(‘Exception Occured’);
                  –debug_log(l_plsql_block);
                  –debug_log(‘Exception is :’||substrb(sqlerrm, 1, 55));
                  NULL;
            END;

            nth := nth + 1;
         END LOOP;

         DBMS_LOB.CLOSE (fil);
      END IF;

      COMMIT;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         k := NULL;
         k := DBMS_LOB.ISOPEN (fil);

         IF k = 1
         THEN
            DBMS_LOB.CLOSE (fil);
         END IF;
      WHEN OTHERS
      THEN
         BEGIN
            — debug_log(‘End of File reached in Exception. Closing file’);
            k := NULL;
            k := DBMS_LOB.ISOPEN (fil);

            IF k = 1
            THEN
               DBMS_LOB.CLOSE (fil);
               COMMIT;
            END IF;
         END;

         –Here call the oe_order_pub API to create the lines passing the line table from this custom table.
   END parse_and_load_file;

What is ASO_ORDER_FEEDBACK_T?

 This articles provides insight into the functionality behind the table ASO_ORDER_FEEDBACK_T and information on how we regained 100GB space by performing certain tasks.

My client is into four years of implementation with a lot of applications implemented in ERP and CRM areas. While performing database audit, our DBA team found that the table ASO_ORDER_FEEDBACK_T was growing at an alarming rate (size was close to 100GB). They wanted the to understand the functionality behind this table and recommendations, if any, can be made to contain the growth. So, before we took any action we had to perform research and recommend an action plan to manage the growth. Here is the simple summary of what we found.

Functional Analysis

As a standard feature in Order Management there is a queue generated whenever a sales order is booked. This table holds the queue which has complete information about a sales order. This is a good feature if we want to execute an action in some other application as soon the order is booked. As a seeded funcationality this queue table holds information which is used by some applications with in Oracle Applications. But as an extension we can always use this queue if we want to communicate with any application of our choice. As an example if we have some custom shipping application and we want to send messages to that system as soon the order is booked, we can make use of this feature. Here is how it works.

This queue is built as soon the order is booked which happens in the private api that is used to create orders: oe_order_pvt.process_order. This in turn calls the package  oe_service_util.notify_oc which builts the queue. This simple article addresses the following questions:

  1. Who subscribed to this message?
  2. Who consumes this message queue?
  3. Can we turn off this so that we can contain this table’s growth?
  4. What is the impact of turning this off?
  5. Can we add our own application get messages from order?

Subscribers

Subscribers to this message can be located in the look up type ASO_ORDER_FEEDBACK_CRM_APPS. All the active lookup codes (enabled flag is checked and end date is less than or equal to today’s date) in this look up type are the subscribers. The number of queues built in this table for each order is equal to the number of active subscribers.You can imagine the growth of this table if you are booking a large volume of the orders on a daily basis and have no consumers for this message based on your business needs. Oracle Applications come with four standard subscribers for this queue that get auto installed: CN (Incentive Compensation), CS (Cusotmer Service and actually used by Install Base), OKS (Service Contracts) and OZF (Funds & Budgets or popularly known as Trade Management as well as Oracle Marketing).

Who Consumes these messages?

The following programs and packages consume the queue when you run the programs. If you do not run these programs obviously the queue grows as soon an order is booked and never gets dequeued.

Program Name Application Package Name Consumes..
Process Old Order Lines – Fulfillable only Install Base csi_order_fulfill_pub.Process_old_order_lines CS Queue
Funds Accrual Engine Funds & Budgets ozf_accrual_engine.get_message OZF Queue
AMS-TM : Funds Accrual Engine Oracle Marketing ams_accrual_engine.get_message OZF Queue
Collect Orders Oracle Sales Compensation cn_collect_orders.collect CN Queue
Service Contracts Order Capture Integration Oracle Service Contracts oks_ocint_pub.oc_interface OKS Queue
  • CS or Install Base queue, when consumed, creates/updates the install base of old fulfilled order lines that have been fulfilled prior to 11.5.6 upgrade. One time usage.
  • Between Oracle Marketing and Fund & Budgets, the OZF queue is consumed, depending on which program and version of applicatons is used. This basically eats into the budgeted funds of the marketing campaign allocated in these applications. These accruals come as price adjustments or promotions from order management. Please make sure you take an expert’s opinion in these applications for more informaton.
  • CN queue is consumed when you collect orders to pay commission for the orders that are booked. This obviously suggests of a business process where booked orders are used as a source to pay commisssion to the sales force.
  • When OKS queue is consumed, it creates a service contract (Service Agreement or Extended Warranty or Warranty depending on the profile option OKS: OM interface Contract Category setup) from order management when a service item is associated to a line that creates/updates the install base. The association of Service Item to the Inventory Items that is trackable in Install Base is done using Service tab in the order lines.

Please refer to respective product documentation for more information on these programs and their functionality.

How to generate a custom queue?

All we need to do is to subscribe your application to this queue. To achieve we enter our custom application name (for example SHIP)  as a lookup code in the lookup type ASO_ORDER_FEEDBACK_CRM_APPS. This will generate the queue into this code as soon the order is booked. To consume this we can use the package aso_order_feedback_pub.get_notice with this application name (SHIP) to read the queue followed by actual work we want to do using the information available in this queue like shipping a custom application.

How to contain the growth of this table if we do not have any consuming application and what is the impact?

Obviously the simplest way to contain this is by disabling the subscribers in the lookup type.But before doing so we should make sure we have no need to run the programs that are mentioned above, otherwise it can cause issues with a number of applications. If we have no business need to run the program, we can safely disable them. This will stop further growth though you are entering new orders and booking them.

What do we do with my existing data in the queue table if we do not have any need to run the programs?

Please refer to the metalink note 181410.1 for more information on this.

What we did?

Following the instructions in the above note, first we dropped the queue. Then after careful analysis we disabled the subscribers to this queue as we do not use them. Then we recreated the queue.

Create a free website or blog at WordPress.com.