How to Configure AME in R12 –  Assign Roles & Create Grants for User
Oracle Approvals Management (AME) functionality is a self-service web application that allows users to
define rules for administering approvals of various types of transactions. Learn how easy it is to use this
powerful functionality to create complex approval scenarios that meet your unique business requirements.
Case studies of recent successful implementations will be presented for PO, AP and HR. Learn how to
accommodate individual employee signing limits, how to integrate workflow timeout functionality with AME.

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.
We are very pleased to announce that Oracle E-Business Suite Release 12.2 is generally available for download now:
  • EBS 12.2 represents our most-groundbreaking release in years (Press Release).  It includes new product functionality, new Fusion Middleware and database components, and introduces new tools for installing, configuring, and maintaining E-Business Suite environments:

    Hundreds of new features

    Includes significant enhancements across the integrated suite of business applications spanning enterprise resource planning, human capital management, and supply chain management.  You can find the complete list here:
    Online Patching
    Apply EBS patches while users are still entering transactions and using the E-Business Suite.  Online Patching uses the Oracle Database’s Edition-Based Redefinition feature and other new technologies to allow the E-Business Suite to be updated while the system is still running. You can learn more about Online Patching via our official documentation and this technical webcast.
    WebLogic Server
    Uses Oracle WebLogic Server, which replaces the Oracle Containers for Java (OC4J) application server used in EBS 12.0 and 12.1.  You can learn more about how this improves the system administration experience via our official documentation and this technical webcast.

    Streamlined installation

    • Option for installing EBS 12.2 on to existing database servers.
    • Capability of installation into existing Real Application Clusters environments.
    • Database deployment on Automatic Storage Management (ASM) and other file systems.
    Upgrading to EBS 12.2
    Is there a direct upgrade path from EBS 11i to 12.2?

    Yes, there is a direct upgrade path from EBS 11.5.10.2 to EBS 12.2.  EBS 11.5.10.2 customers do not have to install an intermediary EBS 12 release (such as 12.1.3) before upgrading to EBS 12.2.  EBS 11.5.10.2 customers must have applied the minimum baseline patch requirements for Extended Support as described in Patch Requirements for Extended Support of Oracle E-Business Suite Release 11.5.10 (Document 883202.1). Customers on earlier EBS 11i releases (such as 11.5.7) need to be at the 11.5.10.2 level plus the minimum baseline patch requirements for Extended Support before they can upgrade to EBS 12.2.
    Is there a direct upgrade path from EBS 12.0 to 12.2?

    Yes, there is a direct upgrade path from EBS 12.0.4 and 12.0.6 to EBS 12.2.  EBS 12.0.4 or 12.0.6 customers do not have to install an intermediary EBS 12 release (such as 12.1.3) before upgrading to EBS 12.2.  Customers on earlier EBS 12.0 releases (such as 12.0.3) will need to be at the 12.0.4 or 12.0.6 level before they can upgrade to EBS 12.2.
    Is there a direct upgrade path from EBS 12.1 to 12.2?

    Yes, there is a direct upgrade path from EBS 12.1.1, 12.1.2, and 12.1.3 to EBS 12.2.
    How can I prepare for EBS 12.2?
      More technical references
     concurrent program can provide output in a language if the language is installed in Oracle. To find out which languages are installed in Oracle you can check this article. Generally seeded programs provide output of a program based on the user preferred language. In this example we have illustrated how to override user preference and provide the output of a concurrent program and give multi lingual output based on a certain rule/condition.

    Step 1: Create Multi language function in the database
    We created a multi language packaged function named, XX_MLS_LANG.GET_LANG. The function expects an input from a concurrent program. This input will come from a concurrent program parameter named, Language. In this example the user will enter a language name and this name will be converted into the language code by the function. For example, if the users enter GERMAN the language function will return D, that is the code in Oracle for German.
    The code for this function is given below.
    CREATE OR REPLACE PACKAGE APPS.xx_mls_lang AUTHID CURRENT_USER
    AS
       FUNCTION get_lang
          RETURN VARCHAR2;
    END xx_mls_lang;
    /
     
    CREATE OR REPLACE PACKAGE BODY apps.xx_mls_lang
    AS
       FUNCTION get_lang
          RETURN VARCHAR2
       IS
          p_lingo              VARCHAR2 (40)   := NULL;
          l_select_statement   VARCHAR2 (4000);
          source_cursor        INTEGER;
          lang_string          VARCHAR2 (240)  := NULL;
          l_lang               VARCHAR2 (30);
          l_lang_str           VARCHAR2 (500)  := NULL;
          l_base_lang          VARCHAR2 (30);
          l_dummy              INTEGER;
          ret_val              NUMBER          := NULL;
          parm_number          NUMBER;
          l_trns_lang_check    NUMBER;
       BEGIN
          -- Parameter Entry
          ret_val := fnd_request_info.get_param_number ('Language', parm_number);
     
          IF (ret_val = -1)
          THEN
             p_lingo := NULL;
          ELSE
             p_lingo := fnd_request_info.get_parameter (parm_number);
          END IF;
     
          -- Get Base Language
          SELECT language_code
            INTO l_base_lang
            FROM fnd_languages
           WHERE installed_flag = 'B';
     
          -- If the user has entered a language/value for the parameter then
          -- extract it the value
          IF p_lingo IS NOT NULL
          THEN
             -- Open the cursor
             source_cursor := DBMS_SQL.open_cursor;
     
             -- Create a query string to get languages based on parameters.
             l_select_statement :=
                'SELECT language_code FROM fnd_languages where nls_language = UPPER(:p_language)';
             DBMS_SQL.parse (source_cursor, l_select_statement, DBMS_SQL.v7);
             DBMS_SQL.bind_variable (source_cursor, ':p_language', p_lingo);
     
             -- Execute the cursor
             DBMS_SQL.define_column (source_cursor, 1, l_lang, 30);
             l_dummy := DBMS_SQL.EXECUTE (source_cursor);
     
             -- If the cursor has returned more than 1 row then
             -- get the output of the cursor into respective variables
             IF DBMS_SQL.fetch_rows (source_cursor) <> 0
             THEN
                DBMS_SQL.COLUMN_VALUE (source_cursor, 1, l_lang);
                l_lang_str := l_lang;
             ELSE
                -- If the cursor returned 0 rows then return the base language
                l_lang_str := l_base_lang;
             END IF;
     
             -- Close the cursor
             DBMS_SQL.close_cursor (source_cursor);
          ELSE
             -- If the user has not entered any value then return the base language
             l_lang_str := l_base_lang;
          END IF;
     
          fnd_file.put_line
             (fnd_file.LOG,
              'Checking to see if the derived language has a translated layout or not'
             );
     
          BEGIN
             -- Check if the language entered by the user is associated to a translated template or not
             SELECT 1
               INTO l_trns_lang_check
               FROM xdo_lobs xl
              WHERE xl.lob_type = 'MLS_TEMPLATE'
                AND xl.trans_complete = 'Y'
                AND xl.LANGUAGE = l_lang_str
                AND xl.lob_code =
                       ( -- Get the actual program name from the MLS request
                        SELECT argument2  -- Prog name
                          FROM fnd_run_req_pp_actions
                         WHERE parent_request_id = fnd_global.conc_request_id -- Request id of the MLS function
                           AND action_type = 6)             -- Template Code
                                                     ;
          EXCEPTION
             WHEN OTHERS
             THEN
                -- If the chosen language does not have an associated template the SQL will fail
                -- and therefore return the default language
                fnd_file.put_line (fnd_file.LOG,
                                      'There is no layout for language: '
                                   || l_lang_str
                                  );
                fnd_file.put_line
                   (fnd_file.LOG,
                       'Therefore we are using the default template for language: '
                    || l_base_lang
                   );
                l_lang_str := l_base_lang;
          END;
     
          RETURN (l_lang_str);
       EXCEPTION
          WHEN OTHERS
          THEN
             DBMS_SQL.close_cursor (source_cursor);
             RAISE;
       END get_lang;
    END xx_mls_lang;
    /

    Step 2: Create an executable for Multi Language
    When the multi language packs are installed in Oracle a new type of concurrent executable is created, Multi Language Function. We shall create a concurrent executable of this type for the database function we have created.

    Step 3: Add the parameter to the concurrent program (Optional)
    In this step we are going to modify the seeded program, Active Users, to provide the output in multi language. Since this program does not take any parameters we are going to add a parameter to this program to accept a language name as a user entry (as explained in Step 1).
    Step 4: Attach the multi language executable
    Now we shall attach the multi language executable to the concurrent program, Active Users, so that the output language is taken from the MLS function.
    Once the language packs are installed a field named, MLS function, is enabled on concurrent program form. Enter the MLS executable here.
    Note: MLS function field has a LOV attached to it. The LOV has the list of executables that are of type Multi Language Function, i.e. executables defined as in Step 2.

    Test the concurrent program
    Now we shall execute the concurrent program to check the output. Open the SRS form
    Now select the program as Active Users.
    We get a prompt for the parameter we had created, i.e. Language. Enter a language, say Spanish.
    Press OK and submit the program.
    Notice that 2 concurrent programs are executed by Oracle instead of 1.
    1. Active Users (Multiple Languages)
    2. ES-ES: (Active Users)
    This is because the first request is for the MLS language function and the second request is for the concurrent program.
    When the concurrent programs complete check the log and output of both the requests.
    • Output of request, Active Users (Multiple Languages)
    There is no output of the request that is kicked off for the MLS function.
    • Log of request, Active Users (Multiple Languages)
    +---------------------------------------------------------------------------+
    Application Object Library: Version : 12.0.0
     
    Copyright (c) 1979, 1999, Oracle Corporation. All rights reserved.
     
    FNDMLSUB module: Multiple Languages
    +---------------------------------------------------------------------------+
     
    Current system time is 15-AUG-2013 08:35:59
     
    +---------------------------------------------------------------------------+
     
    **Starts**15-AUG-2013 08:35:59
    **Ends**15-AUG-2013 08:35:59
    +---------------------------------------------------------------------------+
    Start of log messages from FND_FILE
    +---------------------------------------------------------------------------+
    +---------------------------------------------------------------------------+
    Calling language function xx_mls_lang.get_lang  : 15-AUG-2013 08:35:59
    Language function returned the following languages : E .  : 15-AUG-2013 08:35:59
    +---------------------------------------------------------------------------+
    The following are the details of submitted requests:
    Request ID Language
    ------------------------------------------
         57613357       SPANISH
    +---------------------------------------------------------------------------+
    End of log messages from FND_FILE
    +---------------------------------------------------------------------------+

    Important: When a concurrent request gives output in multiple languages it is the header or the data labels that are changed into different languages. The data remains in the same language as it is stored in the database.
    • Log of request, Active Users (Multiple Languages)
    +---------------------------------------------------------------------------+
    Application Object Library: Version : 12.0.0
     
    Copyright (c) 1979, 1999, Oracle Corporation. All rights reserved.
     
    FNDSCURS module: Usuarios Activos
    +---------------------------------------------------------------------------+
     
    Hora actual del sistema: 15-AGO-2013 08:35:59
     
    +---------------------------------------------------------------------------+
     
    +-----------------------------
    | Iniciando la ejecución del programa simultáneo...
    +-----------------------------
     
    Argumentos
    ------------
    Language='Spanish'
    ------------
     
    APPLLCSP Environment Variable set to :
     
     Current NLS_LANG and NLS_NUMERIC_CHARACTERS Environment Variables are :
    SPANISH_SPAIN.UTF8
     
    ' '
     
    Introduzca la Contraseña:
    REP-0092: Advertencia: Argumento LANGUAGE versión 1.1 no soportado. Use en su lugar la variable de entorno de Idioma Nacional de ORACLE.
    REP-0092: Advertencia: Argumento LANGUAGE versión 1.1 no soportado. Use en su lugar la variable de entorno de Idioma Nacional de ORACLE.
     
    Report Builder: Release 10.1.2.3.0 - Production on Jue Ago 15 08:36:02 2013
     
    Copyright (c) 1982, 2005, Oracle.  All rights reserved.
     
    +---------------------------------------------------------------------------+
    Inicio del log de mensajes de FND_FILE
    +---------------------------------------------------------------------------+
    +---------------------------------------------------------------------------+
    Fin del log de mensajes de FND_FILE
    +---------------------------------------------------------------------------+
     
    Note that the log file has now changed to Spanish. This means that MLS affects data labels, headers and log files but not data.
    Appendix:
    Now if we were to take off the MLS function from Step 4 and executed Active Users concurrent program then Oracle would have executed only 1 request.

    Bar Code Local Setup:

    1) Copy Barcode font in C:WindowsFonts directory.
    2) Copy xdo.cfg in C:Program FilesOracleXML Publisher DesktopTemplate Builder for Wordconfig directory. The sample file is already available when BI Publisher desktop is installed.
    3) Right click the font file and go to properties. Copy the .ttf file name. Double click the font file to get the family name.
    4) Open the xdo.cfg file and paste as follows (My filename is w39elc.ttf and font family is WASP 39 ELC)

    <font family=”WASP 39 ELC” style=”normal” weight=”normal”>  <truetype path=”C:WINDOWSFontsw39elc.ttf” /> </font>

    Bar Code Application Setup:
    Basically this post refers to any font that you want to embed into you output but I was working specifically on demand to insert the barcode.
    So start with something simple. Obtain the font file. In my case I posses “WASP 39 ELC” font. Font file name is w39elc.ttf. Install the font into Windows by double clicking on it and choosing “install”
    Open your RTF template and place the bar code in the location you want.


    So far so good and if you run this template locally on your workstation you will see the bar code. But not in EBS.
      This is what you need to do in order to make it work in EBS
    Open “XML Publisher Administrator” responsibility
    Go to “Administration”-> “Font Files”


    Click on “Create Font File”


    In “Font Name” put the name of the font as it appears in Word. Choose the font file and click “Apply”


    Go to “Administrator”-> “Font Mapping”
    image
    Click on “Create Font Mapping Set”


    Put into “Mapping Name” – Bar Code Fonts, into “Mapping Code” – BAR_CODE_FONTS, into “Type” –FO To PDF and click “Apply”


    Click on the Bar Code Fonts link


    Click on “Create Font Mapping”


    Define Font Mapping as appears in the print screen bellow and click “Continue”


    Ok, now you need  template to “know” the bar code font we just created.


    Open template definition and go to “Edit Configuration”
    Expand “FO Processing” and put into “Font Mapping Set” – Bar Code Fonts and click “Apply”.


    Now you can run your template and it will display the bar code properly.