Search This Blog

Sunday, June 30, 2013

Load PDF File attachment using API

Load PDF File attachment using API

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. 

CREATE OR REPLACE DIRECTORY in_file_loc AS '/tmp';

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. 

CREATE TABLE test_files  (p_id NUMBER,
                          pl_name VARCHAR2(100),
                          pl_pict BLOB);

Step 3:
Now load the file into this table. 

DECLARE
   x_blob                BLOB;
   fils                  BFILE   := BFILENAME ('IN_FILE_LOC', 'G74822LRs.pdf');
   blob_length           INTEGER;
BEGIN
-- Obtain the size of the blob file
   DBMS_LOB.fileopen (fils, DBMS_LOB.file_readonly);
   blob_length := DBMS_LOB.getlength (fils);
   DBMS_LOB.fileclose (fils);

   -- Insert a new record into the table containing the
   -- filename you have specified and a LOB LOCATOR.
   -- Return the LOB LOCATOR and assign it to x_blob.
   INSERT INTO test_files (pl_id,pl_name,pl_pict)
        VALUES (4, 'G74822LRs.pdf', EMPTY_BLOB ())
     RETURNING pl_pict
          INTO x_blob;

   -- Load the file into the database as a BLOB
   DBMS_LOB.OPEN (fils, DBMS_LOB.lob_readonly);
   DBMS_LOB.OPEN (x_blob, DBMS_LOB.lob_readwrite);
   DBMS_LOB.loadfromfile (x_blob, fils, blob_length);
   -- Close handles to blob and file
   DBMS_LOB.CLOSE (x_blob);
   DBMS_LOB.CLOSE (fils);
   COMMIT;
   -- Confirm insert by querying the database
   -- for LOB length information and output results
   blob_length := 0;

   SELECT DBMS_LOB.getlength (pl_pict)
     INTO blob_length
     FROM test_files
    WHERE pl_name = 'G74822LRs.pdf';

   DBMS_OUTPUT.put_line ('Successfully inserted BLOB ''' ||'G74822LRs.pdf' || ''' of size ' || blob_length || ' bytes.');
END;

Step 4:
Now that we have file in the staging table, we will start loading the file into FND schema of Oracle Applications/

DECLARE
   TYPE result_set_type IS REF CURSOR;

   l_name              VARCHAR2 (100);
   l_doc_size          NUMBER;
   l_result_set_curr   result_set_type;
   x_access_id         NUMBER;
   x_file_id           NUMBER;
   p_file_name         VARCHAR2 (100)  := 'G74822LRs.pdf';

   PROCEDURE load_file_details (p_name IN VARCHAR2, result_set_curr OUT result_set_type)
   AS
      l_error   VARCHAR2 (2000);
   BEGIN
      INSERT INTO fnd_lobs_document
                  (NAME, mime_type, doc_size, content_type, blob_content)
         SELECT pl_name, 'application/pdf', DBMS_LOB.getlength (pl_pict), 'BINARY', pl_pict
           FROM test_files
          WHERE pl_name = p_name;

      OPEN result_set_curr FOR
         SELECT blob_content
           FROM fnd_lobs_document
          WHERE NAME = p_name;
   EXCEPTION
      WHEN OTHERS
      THEN
         NULL;
         l_error := 'LOAD_FILE_DETAILS - OTHERS' || SUBSTR (SQLERRM, 2000);
         DBMS_OUTPUT.put_line (l_error);
   END load_file_details;

   PROCEDURE upload_file (v_filename IN VARCHAR2, x_access_id OUT NUMBER, x_file_id OUT NUMBER)
   AS
      v_access_id   NUMBER;
      v_file_id     NUMBER;
      x_errbuf      VARCHAR2 (200);
   BEGIN
      v_access_id := fnd_gfm.authorize (NULL);
      x_access_id := v_access_id;
      DBMS_OUTPUT.put_line ('Access id :' || v_access_id);
      -- The function fnd_gfm.confirm_upload return the file id
      v_file_id :=
         fnd_gfm.confirm_upload (access_id            => v_access_id
                               , file_name            => v_filename
                               , program_name         => 'TEST'
                               , program_tag          => 'TEST'
                               , expiration_date      => NULL
                               , LANGUAGE             => 'US'
                               , wakeup               => TRUE
                                );
      x_file_id := v_file_id;
      DBMS_OUTPUT.put_line ('File id :' || x_file_id);
   EXCEPTION
      WHEN OTHERS
      THEN
         x_errbuf := 'Procedure upload_file errored out with the following error : ' || SQLERRM;
         DBMS_OUTPUT.put_line (x_errbuf);
   END upload_file;
BEGIN
   fnd_global.apps_initialize (1318, 20420, 1);
   load_file_details (p_name => p_file_name, result_set_curr => l_result_set_curr);
   upload_file (v_filename => p_file_name, x_access_id => x_access_id, x_file_id => x_file_id);
   COMMIT;
END;

Step 5:
Now let us use item API to load item and get the item_id.

CREATE OR REPLACE PACKAGE xx_create_item
IS
   g_miss_num    CONSTANT NUMBER       := 9.99e125;
   g_miss_char   CONSTANT VARCHAR2 (1) := CHR (0);
   g_miss_date   CONSTANT DATE         := TO_DATE ('1', 'j');
   g_false       CONSTANT VARCHAR2 (1) := fnd_api.g_false;                                                                
   g_true        CONSTANT VARCHAR2 (1) := fnd_api.g_true;

   PROCEDURE create_item (
      p_item_number         IN       VARCHAR2
    , p_description         IN       VARCHAR2
    , p_organization_id     IN       NUMBER
    , p_item_type           IN       VARCHAR2
    , x_inventory_item_id   OUT      NUMBER
    , x_organization_id     OUT      NUMBER
    , x_return_status       OUT      VARCHAR2
    , x_msg_count           OUT      NUMBER
    , x_msg_data            OUT      VARCHAR2
   );

   PROCEDURE create_item1 (
      p_item_number         IN       VARCHAR2
    , p_description         IN       VARCHAR2
    , p_organization_id     IN       NUMBER
    , p_item_type           IN       VARCHAR2
    , x_inventory_item_id   OUT      NUMBER
    , x_organization_id     OUT      NUMBER
    , x_return_status       OUT      VARCHAR2
    , x_msg_count           OUT      NUMBER
    , x_msg_data            OUT      VARCHAR2
   );
END xx_create_item;
/

CREATE OR REPLACE PACKAGE BODY xx_create_item
IS
   PROCEDURE create_item (
      p_item_number         IN       VARCHAR2
    , p_description         IN       VARCHAR2
    , p_organization_id     IN       NUMBER
    , p_item_type           IN       VARCHAR2
    , x_inventory_item_id   OUT      NUMBER
    , x_organization_id     OUT      NUMBER
    , x_return_status       OUT      VARCHAR2
    , x_msg_count           OUT      NUMBER
    , x_msg_data            OUT      VARCHAR2
   )
   IS
      l_template_id       NUMBER;
      x_item_id           NUMBER;
      x_org_id            NUMBER;
      l_item_number       VARCHAR2 (100);
      l_description       VARCHAR2 (4000);
      l_organization_id   NUMBER;
      v_msg_index_out     NUMBER;
      v_message           VARCHAR2 (100);
   BEGIN
      SELECT template_id
        INTO l_template_id
        FROM mtl_item_templates_b
       WHERE template_name = p_item_type;                                                                     

      l_item_number := p_item_number;
      l_description := p_description;
      l_organization_id := l_organization_id;
      ego_item_pub.process_item (p_api_version                 => 1.0
                               , p_transaction_type            => 'CREATE'
                               , p_language_code               => 'US'
                               , p_template_id               => 207
                               , p_organization_id             => 204
                               , p_master_organization_id      => 204
                               , p_description                 => 'TEST113'
                               , p_long_description            => 'TEST113'
                               , p_item_number                 => 'TEST113'
                               , p_segment1                    => 'TEST113'
                               , x_inventory_item_id           => x_inventory_item_id
                               , x_organization_id             => x_organization_id
                               , x_return_status               => x_return_status
                               , x_msg_count                   => x_msg_count
                               , x_msg_data                    => x_msg_data
                                );

      IF x_msg_count > 0
      THEN
         FOR v_index IN 1 .. x_msg_count
         LOOP
            fnd_msg_pub.get (p_msg_index => v_index, p_encoded => 'F', p_data => x_msg_data, p_msg_index_out => v_msg_index_out);
            v_message := SUBSTR (x_msg_data, 1, 200);
            DBMS_OUTPUT.put_line (x_msg_data);
            DBMS_OUTPUT.put_line ('============================================================');
         END LOOP;

         DBMS_OUTPUT.put_line (SUBSTR (v_message, 1, 2000));
         DBMS_OUTPUT.put_line ('============================================================');
      END IF;
   END;

   PROCEDURE create_item1 (
      p_item_number         IN       VARCHAR2
    , p_description         IN       VARCHAR2
    , p_organization_id     IN       NUMBER
    , p_item_type           IN       VARCHAR2
    , x_inventory_item_id   OUT      NUMBER
    , x_organization_id     OUT      NUMBER
    , x_return_status       OUT      VARCHAR2
    , x_msg_count           OUT      NUMBER
    , x_msg_data            OUT      VARCHAR2
   )
   IS
      l_template_id       NUMBER;
      l_item_number       VARCHAR2 (100);
      l_description       VARCHAR2 (4000);
      l_organization_id   NUMBER;
      v_msg_index_out     NUMBER;
      v_message           VARCHAR2 (100);
   BEGIN
      l_item_number := p_item_number;
      l_description := p_description;
      l_organization_id := p_organization_id;
      ego_item_pub.process_item (p_api_version            => 1.0
                               , p_transaction_type       => 'CREATE'
                               , p_language_code          => 'US'
                               , p_template_name          => p_item_type
                               , p_item_number            => l_item_number
                               , p_segment1               => l_item_number
                               , p_organization_id        => l_organization_id
                               , p_description            => l_item_number
                               , p_long_description       => l_item_number
                               , x_inventory_item_id      => x_inventory_item_id
                               , x_organization_id        => x_organization_id
                               , x_return_status          => x_return_status
                               , x_msg_count              => x_msg_count
                                );
   END;
END xx_create_item;
/

SHOW errors
/
DECLARE
   v_msg_index_out   NUMBER;
   x_item_id         NUMBER;
   x_org_id          NUMBER;
   x_return_status   VARCHAR2 (1);
   x_msg_count       NUMBER;
   x_msg_data        VARCHAR2 (4000);
   v_message         VARCHAR2 (4000);
BEGIN
   fnd_global.apps_initialize (1318, 50583, 401);
   inv_globals.set_org_id (204);
   xx_create_item.create_item1 (p_item_number            => 'TEST111'
                             , p_description            => 'TEST111'
                             , p_organization_id        => 204
                             , p_item_type              => 'Finished Good'
                             , x_inventory_item_id      => x_item_id
                             , x_organization_id        => x_org_id
                             , x_return_status          => x_return_status
                             , x_msg_count              => x_msg_count
                             , x_msg_data               => x_msg_data
                              );
         DBMS_OUTPUT.put_line ('Return Status is :'||x_return_status);                             
         DBMS_OUTPUT.put_line ('Message Count is :'||x_msg_count);
         DBMS_OUTPUT.put_line ('Create Item ID  is :'||x_item_id);
         DBMS_OUTPUT.put_line ('Created in Organization is :'||x_org_id);

   IF x_msg_count > 0
   THEN
      FOR v_index IN 1 .. x_msg_count
      LOOP
         fnd_msg_pub.get (p_msg_index => v_index, p_encoded => 'F', p_data => x_msg_data, p_msg_index_out => v_msg_index_out);
         v_message := SUBSTR (x_msg_data, 1, 200);
         DBMS_OUTPUT.put_line (x_msg_data);
         DBMS_OUTPUT.put_line ('============================================================');
      END LOOP;

      DBMS_OUTPUT.put_line (SUBSTR (v_message, 1, 2000));
      DBMS_OUTPUT.put_line ('============================================================');
   END IF;
END;
/

DECLARE
   v_msg_index_out   NUMBER;
   x_item_id         NUMBER;
   x_org_id          NUMBER;
   x_return_status   VARCHAR2 (1);
   x_msg_count       NUMBER;
   x_msg_data        VARCHAR2 (4000);
   v_message         VARCHAR2 (4000);
BEGIN
   --fnd_global.apps_initialize (1318, 50583, 401);
   inv_globals.set_org_id (204);
   xx_create_item.create_item1 (p_item_number            => 'TEST111'
                             , p_description            => 'TEST111'
                             , p_organization_id        => 204
                             , p_item_type              => 'Finished Good'
                             , x_inventory_item_id      => x_item_id
                             , x_organization_id        => x_org_id
                             , x_return_status          => x_return_status
                             , x_msg_count              => x_msg_count
                             , x_msg_data               => x_msg_data
                              );
         DBMS_OUTPUT.put_line ('Return Status is :'||x_return_status);                             
         DBMS_OUTPUT.put_line ('Message Count is :'||x_msg_count);
         DBMS_OUTPUT.put_line ('Create Item ID  is :'||x_item_id);
         DBMS_OUTPUT.put_line ('Created in Organization is :'||x_org_id);

   IF x_msg_count > 0
   THEN
      FOR v_index IN 1 .. x_msg_count
      LOOP
         fnd_msg_pub.get (p_msg_index => v_index, p_encoded => 'F', p_data => x_msg_data, p_msg_index_out => v_msg_index_out);
         v_message := SUBSTR (x_msg_data, 1, 200);
         DBMS_OUTPUT.put_line (x_msg_data);
         DBMS_OUTPUT.put_line ('============================================================');
      END LOOP;

      DBMS_OUTPUT.put_line (SUBSTR (v_message, 1, 2000));
      DBMS_OUTPUT.put_line ('============================================================');
   END IF;
END;

Step 6:
Use this inventory_item_id, organization_Id, x_access_id and x_file_id to load PDF file against this item. 

DECLARE
   TYPE result_set_type IS REF CURSOR;

   l_name              VARCHAR2 (100);
   l_doc_size          NUMBER;
   l_result_set_curr   result_set_type;
   x_access_id         NUMBER;
   x_file_id           NUMBER;
   p_file_name         VARCHAR2 (100)  := 'G74822LRs.pdf';

   PROCEDURE attach_file (p_access_id IN NUMBER, p_file_Id in number, p_filename IN VARCHAR2)
   IS
   BEGIN
          fnd_webattch.add_attachment (seq_num                   => 100
                                     ,category_id               => 1
                                     ,document_description      => 'Test'
                                     ,datatype_id               => 6
                                     ,text                      => NULL
                                     ,file_name                 => p_filename
                                     ,url                       => NULL
                                     ,function_name             => 'INVIDITM'
                                     ,entity_name               => 'MTL_SYSTEM_ITEMS'
                                     ,pk1_value                 => 204 --organization_id
                                     ,pk2_value                 => 72627 --Inventory_item_Id
                                     ,pk3_value                 => NULL
                                     ,pk4_value                 => NULL
                                     ,pk5_value                 => NULL
                                     ,media_id                  => p_file_id
                                     ,user_id                   => 1318
                                     ,usage_type                => 'O'
                                     );
      DBMS_OUTPUT.put_line ('File Attached!');
   EXCEPTION
      WHEN OTHERS
      THEN
         DBMS_OUTPUT.put_line ('error in loading the attachement');
   END attach_file;
BEGIN
   fnd_global.apps_initialize (1318, 20420, 1);
   attach_file (p_access_id => x_access_id, p_file_id=>x_file_id,p_filename => p_file_name);
   COMMIT;
END;

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

No comments:

Post a Comment