DCP

Tuesday 6 December 2016

Assigning Responsibility to many users in bulk

CREATE OR REPLACE PROCEDURE XX_bulk_resp_assignment AS

  l_responsibility_key   VARCHAR2(250) := 'XX_AP_INQUIRY';
  l_resp_app             VARCHAR2(30) := 'SQLAP';
  l_security_group_key   VARCHAR2(100) := 'STANDARD';
  l_processed_count      NUMBER := 0;
  l_new_asg_count        NUMBER := 0;
  l_reactivate_asg_count NUMBER := 0;
  l_no_action_count      NUMBER := 0;
  l_asg_exists_count     NUMBER := 0;

  l_error_count NUMBER := 0;

  CURSOR csr_act_emps IS
    SELECT user_name FROM XXhr_active_employees emps WHERE emps.assignment_primary_flag = 'Y' ORDER BY user_name;

  CURSOR csr_chk_resp_exists(p_user_name VARCHAR2) IS
    SELECT 'x' exist,
           decode(sign(nvl(c.end_date, SYSDATE + 1) - SYSDATE), 1, 'A', 'I') user_status,
           decode(sign(nvl(a.end_date, SYSDATE + 1) - SYSDATE), 1, 'A', 'I') asg_status,
           c.user_name,
           a.start_date
      FROM fnd_user_resp_groups_direct a,
           fnd_responsibility_vl       b,
           fnd_user                    c,
           XXhr_active_employees      d
     WHERE a.responsibility_id = b.responsibility_id
       AND b.responsibility_key = l_responsibility_key
       AND c.user_id = a.user_id
       AND c.user_name = p_user_name
       AND d.user_name = c.user_name;

  r_exists csr_chk_resp_exists%ROWTYPE;

  l_file       utl_file.file_type;
  l_output_dir VARCHAR2(30);

BEGIN


  SELECT instance_name INTO l_output_dir FROM v$instance;
  l_output_dir := '/applcsf/' || l_output_dir || '/temp';

  l_file := utl_file.fopen(l_output_dir, 'XX_bulk_resp_asg2.log', 'A');
  
  IF (l_file.id IS NOT NULL) THEN
    dbms_output.put_line('file opened');
  ELSE 
    dbms_output.put_line('error opening file');
  END IF;
    
  
  -- Sync program required to be run in Prod before running this procedure;

  /*BEGIN
    utl_file.put_line(l_file, 'calling sync prgram ...');
    WF_LOCAL_SYNCH.BulkSynchronization('ALL');
    
    utl_file.put_line(l_file, 'Sync completed ...');
    COMMIT;
  EXCEPTION
     WHEN OTHERS THEN
        utl_file.put_line(l_file, 'ERROR: '||SQLERRM); 
  END;*/
  utl_file.fflush(l_file);

  FOR r1 IN csr_act_emps LOOP
    r_exists := NULL;
  
    OPEN csr_chk_resp_exists(r1.user_name);
    FETCH csr_chk_resp_exists
      INTO r_exists;
    CLOSE csr_chk_resp_exists;
  
    utl_file.put(l_file, r1.user_name || ',');
  
    BEGIN
    
      IF r_exists.exist IS NULL THEN
      
        utl_file.put(l_file, 'New Assignment' || chr(10));
      
        fnd_user_pkg.addresp(username       => r1.user_name,
                             resp_app       => l_resp_app,
                             resp_key       => l_responsibility_key,
                             security_group => l_security_group_key,
                             description    => NULL,
                             start_date     => SYSDATE,
                             end_date       => NULL);
        l_new_asg_count := l_new_asg_count + 1;
      
      ELSIF r_exists.user_status = 'A' AND r_exists.asg_status = 'I' THEN
      
        utl_file.put(l_file, 'Updating Existing Assignment' || chr(10));
      
        fnd_user_pkg.addresp(username       => r1.user_name,
                             resp_app       => l_resp_app,
                             resp_key       => l_responsibility_key,
                             security_group => l_security_group_key,
                             description    => NULL,
                             start_date     => r_exists.start_date,
                             end_date       => NULL);
        l_reactivate_asg_count := l_reactivate_asg_count + 1;
      
      ELSIF r_exists.user_status = 'A' AND r_exists.asg_status = 'A' THEN
        utl_file.put(l_file, 'No Action Active Resp Assignment already exists' ||chr(10));
        l_no_action_count := l_no_action_count + 1;
      
      ELSIF r_exists.user_status = 'I' THEN
        utl_file.put(l_file, 'No Action, Inactive User'|| chr(10));
        l_asg_exists_count := l_asg_exists_count + 1;
      
      END IF;
      
    EXCEPTION
      WHEN OTHERS THEN
        utl_file.put_line(l_file, 'Error: ' || SQLERRM);
      
        l_error_count := l_error_count + 1;

        IF l_error_count >= 10 THEN
          EXIT;
        END IF;
      
    END;
  
    l_processed_count := l_processed_count + 1;
    
    ROLLBACK;
    
    utl_file.fflush(l_file);
    
  END LOOP;

  utl_file.put_line(l_file, '');
  utl_file.put_line(l_file,'l_new_asg_count: ' || l_new_asg_count);
  utl_file.put_line(l_file,'l_reactivate_asg_count: ' || l_reactivate_asg_count);
  utl_file.put_line(l_file,'l_no_action_count: ' || l_no_action_count);
  utl_file.put_line(l_file,'l_asg_exists_count: ' || l_asg_exists_count);
  utl_file.put_line(l_file,'l_processed_count: ' || l_processed_count);
  utl_file.put_line(l_file,'l_error_count: ' || l_error_count);

  
  utl_file.fclose(l_file);

  --COMMIT;
END;

Tuesday 18 October 2016

Query to retrieve Invoice Holds


SELECT vnd.vendor_name, aia.invoice_num, pha.segment1 po_number, pla.line_num, ah.hold_lookup_code, ah.release_lookup_code,
   (nvl((pda.quantity_ordered - nvl(pda.quantity_cancelled, 0)) * pll.price_override, 0)) AS ordered_amount,
   (pda.amount_billed) AS billed_amount,
   (pda.amount_billed - (nvl((pda.quantity_ordered - nvl(pda.quantity_cancelled, 0)) * pll.price_override, 0))) difference,
   pda.quantity_ordered, pda.quantity_delivered
FROM
    apps.ap_holds_all ah,
    apps.po_line_locations_all pll,
    apps.ap_invoices_all aia,
    apps.po_distributions_all pda,
    apps.po_lines_all pla,
    apps.po_headers_all pha,
    apps.ap_suppliers vnd
WHERE ah.line_location_id = pll.line_location_id
    AND ah.invoice_id = aia.invoice_id
    AND pla.po_line_id = pll.po_line_id
    AND pda.line_location_id = pll.line_location_id
    AND pha.po_header_id = pla.po_header_id
    AND ah.creation_date BETWEEN (SYSDATE - 120) AND SYSDATE
    AND vnd.vendor_id = pha.vendor_id
    ORDER BY vendor_name, invoice_num, pha.segment1, pla.line_num;

Query to find iSupplier Users list

Query to find iSupplier Users list


SELECT WEB_USER_ID, USR.USER_NAME, USR.EMAIL_ADDRESS, AP_SUPP.VENDOR_NAME
  FROM AK_WEB_USER_SEC_ATTR_VALUES A, AP_SUPPLIERS AP_SUPP, FND_USER USR
 WHERE ATTRIBUTE_CODE = 'ICX_SUPPLIER_ORG_ID'
   AND ATTRIBUTE_APPLICATION_ID = 177
   AND NUMBER_VALUE = AP_SUPP.VENDOR_ID
   AND USR.USER_ID = A.WEB_USER_ID;



Thursday 6 October 2016

BI Publisher: Apply formatting on Group of rows based on data



Output Needed:

Quick Summary of Steps:



Detail of each step:










1. InitVarBIDNO
<?xdoxslt:set_variable($_XDOCTX, 'PREV_BIDNO', '0')?>


2. InitVarCount: 
<?xdoxslt:set_variable($_XDOCTX, 'XXCOUNT', 1)?>


3. For Each
<?for-each:G_BOARD_DOC?>  
<?sort:MASTER_RFQ_NUM;'ascending';data-type='text'?> 
<?sort:BDOC_TYPE;'descending';data-type='text'?> 
<?sort:VENDOR_NAME;'ascending';data-type='text'?>


4.UpdateBdocCount
<?if:xdoxslt:get_variable($_XDOCTX,'PREV_BIDNO')!=MASTER_RFQ_NUM?><?xdoxslt:set_variable($_XDOCTX, 'XXCOUNT', xdoxslt:get_variable($_XDOCTX,'XXCOUNT')+1)?><?end if?>


5. IfSameBdocAsPreviousRow
<?if@row:xdoxslt:get_variable($_XDOCTX,'XXCOUNT') mod 2=0?>
<xsl:attribute name="color" xdofo:ctx="incontext">rgb(153, 0, 0)</xsl:attribute>
<?end if?>


6. UpdatePrevValue
<?xdoxslt:set_variable($_XDOCTX, 'PREV_BIDNO',MASTER_RFQ_NUM)?> 



Thursday 22 September 2016

List Responsibilities have specific Function

select responsibility_name
from   FND_responsibility_vl fr
        , FND_MENUS fm
        , FND_COMPILED_MENU_FUNCTIONS fmf
       ,fnd_Form_functions_vl ff
WHERE ff.USER_FUNCTION_NAME = 'View Suppliers'   --1
AND     ff.function_id                 = fmf.function_id    --2
AND     fmf.menu_id                  = fm.menu_id         --3
AND     fm.menu_id                   = fr.menu_id          --4
AND responsibility_name LIKE 'D%';

SQLFND - Query to Find who has access to given Responsibility

SELECT fu.user_id, fu.user_name, fu.email_address
    FROM fnd_user_resp_groups_direct furg,
         fnd_user fu,
         fnd_responsibility_tl fr
   WHERE     UPPER (fr.responsibility_name) = UPPER ('&Enter_Resp_Name')
         AND fr.responsibility_id = furg.responsibility_id
         AND furg.user_id = fu.user_id
         AND NVL(furg.end_date, SYSDATE) > SYSDATE
         AND fu.end_date IS NULL
         AND fr.language = USERENV ('LANG')
ORDER BY fu.user_name;

Tuesday 13 September 2016

Oracle APPS Forms Development Quick Reference/Checklist



SQL Coding Guidelines
If you want to SELECT into a procedure parameter, declare the parameter as IN OUT, whether or not you reference the parameter value, unless the parameter is a field.
To handle NO_DATA_FOUND exceptions, write an exception handler. Do not code COUNT statements to detect the existence of rows unless that is your only concern.
Do not check for errors due to database integrity problems. For example, if a correct database would have a table SYS.DUAL with exactly one row in it, you do not need to check if SYS.DUAL has zero or more than one row or if SYS.DUAL exists.
Trigger style should be either Override or Before.
When-Create-Record fires even when insert_allowed is set to null. Code logic to test first if the record insert allowed and then allow the logic to be executed.
Following is the checklist of all the properties or code that should be set or written in:

Property Classes

1. Have property classes been applied to each corresponding form builder object? Such as
   Windows, canvases, blocks, items etc.

Module:

1. Does module name match exactly with form name?
2. Has first navigation data block been set?

Window

Non Modal Windows
1. Have window positioning logic been coded in app_custom? (app_custom.open_window)
2. Have a proper title been assigned to the main and detail window?
3. Have the window opening and closing logic been coded into app_custom? (app_custom.open_window and app_custom.close_window).
4. Have the menu entries been appropriately enabled and disabled for the form?
5. Have you assigned the content canvas of the main window to the dialog window (rule)?

Block

1. Have you set the navigation properties of each block?
Dialog Blocks
1. Have you coded the logic to disable the key triggers for Dialog Blocks?
2. Have you set the previous and next navigation data block property to itself (disable tabs)
   for the dialog block?
Single Record Blocks:
1. Have you kept the navigation to same record for single block window?
2. Have you disabled first record, last record, pevious record and next record menu entries?
   (5-14).
3. Have you disabled KEY-CREREC, KEY-DOWN, KEY-NEXT? (Disble only if required)
Multi-Record Block:
1. Have you set the navigation style for multi-record block to Change Record?
2. Have you accounted for the situation when drilling down to detail is not allowed?
Master-Detail Block:
1. Have you set the coordination property to prevent Masterless Operation?
2. Have you set the Master-Detail property to ISOLATED?
3. Have you set the property of dialog detail block to DEFERRED?
In Oracle Forms, you need to change the block Key Mode property to Non–Updatable to turn off Oracle Forms default ROWID references for blocks based on views. Specify the primary keys for your view by setting the item level property Primary Key to True. For example, a view based on the EMP table has the columns ROW_ID, EMPNO, ENAME, DEPTNO, and DNAME. Set the Key Mode property of block EMP_V to Non–Updatable, and set the Primary Key property of EMPNO to True. If your block is based on a table, the block Key Mode should be Unique.

on-insert:

1. Does your trigger included the 'OR is null' clause for null allowed columns and vice versa.

on-lock:

1. does the lock statement contains RTRIM for db side fields.

Text Items:

1.       Have you applied the CREATION_OR_LAST_UPDATE property class to WHO columns (only CREATION_DATE and LAST_UPDATE_DATE) of all you block fields?
2.       Have you set the query length of all your text items to 255 characters?
3.       Have you applied DISPLAY_ITEMS PC to all your hidden placeholder items? (items with null canvas value)

Pop lists:

1.       If you have changing pop lists make sure each of the list populated contains the default value set at design time.

Buttons:

1.       Have you set all the buttons property to Mouse Navigate NO.?
2.       Have you set the ‘fire-in-enter-query-mode’ property appropriately to each mouse button?
3.       Have you called APP_VALIDATE on each button before performing the button associated operations?

List Of Values:

1.       Does your LOV restrict user only to valid values? (not applicable in query find windows only)
2.       Does the title of the LOV correspond to the name of the object in the LOV and is it plural?
3.       Prompt of the first item matches the prompt of the item which invoked the LOV?
4.       Have you reset the RECORD_STATUS to query in POST-QUERY trigger?
5.       Have you decoded ‘Y’ to ‘*’ and ‘N’ to ‘NULL’ in LOV values?
6.    You must not populate hidden fields by returning values in them in Enter-Query mode.
Check all the constraints mentioned in the forms specifications. Most of common of them Unique and foreign key constraints.
1. For each sub-function a separate menu should be created specific to a specific parent menu entry.
2. For sub-menu there should not be any prompt but they must be included in the menu.
3. Assign a menu entry a sub-menu to create a tree like structure.
4. Setup and Reports must exist at the top level entry.
5. The user function names defined in the Form Functions form are displayed in menu entries.
6. Function names should be <appl_prefix>_<form_name>_<mode> such as XXCS_XCSINVEN_INQUIRY for invoice entry form of XXCS application. If calling a form of any other module then the convention remains same such as XXCS_FNDRSRUN.
7. Hide sub-functions as opposed to enable/disable, if the function is not available for a particular user.
8. Sub-function menu is place below the form function entry.
9. A menu of sub-functions always assumes the name of the form entry with”_MENU” appended, for example:”PO_POXPOMPO_MENU”. The user menu name should be the <formname>: Subfunctions, for example:”Purchase Orders: Subfunctions”.
10. All sub-functions for each form are predefined by the developer, and are named <form>_<subfunction>, for example:”PO_POXPOMPO_DELETE”.

11. Where there are many restrictable subfunctions for a particular form, and those subfunctions group well into categories (Approvals, forexample), group the Subfunctions according to their category, creating for example, ”PO_POXPOMPO_APPROVALS_MENU”,

Creating Descriptive Flexfields

1.     Register key flex fields.                                                                                                                                                        
2.     Assign null canvas to all DFF columns.                                                                                                                               
3.     Apply TEXT_ITEM propertly class to attribute and attribute category columns.                                                        
4.     Set query length to 255.
5.     Create DFF standard displayed field (contatenated segment field) as 2000 characters.                                                     
6.     Name the field as DESC_FLEX                                                                                                                                
7.     Apply the property class TEXT_ITEM_DESC_FLEX.                                                                                                        
8.     Apply the appropriate canvas to DESC_FLEX.                                           
9.     Attach ENABLE_LIST_LAMP LOV from the template form to the the displayed field                                                           
10.  Set validate from list property set to no.                                                                                                                              
11.  Call your flex field definition procedure (FND_DESCR_FLEX.DEFINE) from WHEN-NEW-FORM-INSTANCE. After the define procedure you may call UPDATE_DEINITION procedure to enable, disable or update flexfield by passing appropriate paramenter depending on the form logic.
12.  Call FND_FLEX.EVENT from PRE–QUERY, POST–QUERY, PRE–INSERT, PRE–UPDATE, WHEN–VALIDATE–RECORD, WHEN–NEW–ITEM–INSTANCE and WHEN–VALIDATE–ITEM triggers defined at form level. Make sure these triggers are not overidden by the block or item level triggers. If required set record or item level triggers execution style to BEFORE so that the form level triggers still execute. If setting record status to query from post-query trigger at block level that trigger’s execution style must be set to AFTER.                                                                                              
FND_DESCR_FLEX.DEFINE (
/* Arguments that specify the flexfield location */
BLOCK=>’block_name’,
FIELD=>’field_name’,
[DESCRIPTION=>’description_field_name’,]
[DATA_FIELD=>’concatenated_hidden_IDs_field’,]
/* Arguments that specify the flexfield */
APPL_SHORT_NAME=>’application_short_name’,
DESC_FLEX_NAME=>’descriptive flexfield_name’
/* other optional parameters */
[VDATE=>’date’,]
[TITLE =>’Title’,]
[AUTOPICK=>’ {Y|N}’,]
[USEDBFLDS=>’ {Y|N}’,]
[READ_ONLY=>’ {Y|N}’,]
[LOCK_FLAG=>’ {Y|N}’,]
[HELP=>’APPL=application_short_name;
TARGET=target_name’,]
[CONTEXT_LIKE=>’WHERE_clause_fragment’}
);

Key Flexfields

Table Specifications
Combinations Table
Create a combinations table. Table specifications include
XXX_ID                  NUMBER 38 NOT NULL,
STRUCTURE_ID            NUMBER (38) NOT NULL,
SEGMENT 1…N             VARCHAR2 (60) NULL
ENABLED_FLAG            VARCHAR2 (1) NOT NULL
SUMMARY_FLAG            VARCHAR2 (1) NOT NULL
START_DATE_ACTIVE       DATE NULL
END_DATE_ACTIVE         DATE NULL
DERIVED_COLUMN          ANY_DATA_TYPE NULL (Contains segment qualifier values, can be defined with any valid name)
WHO columns
Create a special maintenance form to define valid key combinations.
Define unique index on XXX_ID column.
Create an ORACLE sequence for your column with the same grants and synonyms as your combinations table (for insert privileges). Name your sequence YOUR_TABLE_NAME_S.
Register your key flex field table.
Foreign Key Reference Table
Define unique id column exactly the same as in combinations table (may or may not be null)
Define structure id column exactly the same as in combinations table (may or may not be null) {pass by num parameter or make a corresponding field on the form}
Adding flexfields to forms
Create hidden id fields (unique_id, structure field (optional) and segment fields (optional)).
Set query length of 2000 for hidden id field and 255 for all other fields mentioned above.
Create concatenated segments field with varchar2 (2000)
Apply text_item property class to each the above mentioned fields.
Attach ENABLE_LIST_LAMP LOV from the template form to the concatenated (displayed field) and set validate from list to no
Call your flex field definition procedure (FND_KEY_FLEX.DEFINE) from WHEN-NEW-FORM-INSTANCE. After the define procedure you may call UPDATE_DEINITION procedure to enable, disable or update flexfield by passing appropriate paramenter depending on the form logic.
Call FND_FLEX.EVENT from PRE–QUERY, POST–QUERY, PRE–INSERT, PRE–UPDATE, WHEN–VALIDATE–RECORD, WHEN–NEW–ITEM–INSTANCE and WHEN–VALIDATE–ITEM triggers defined at form level. Make sure these triggers are not overidden by the block or item level triggers. If required set record or item level triggers execution style to BEFORE so that the form level triggers still execute. If setting record status to query from post-query trigger at block level that trigger’s execution style must be set to AFTER.

FND_KEY_FLEX.DEFINE (
BLOCK=>’ORDERS’,
FIELD=>’KFF_CONCATENATED_VALUES’,
APPL_SHORT_NAME=>’SQLGL’,
CODE=>’GL#’,
NUM=>’101’,
DISPLAYABLE=>’ALL’
INSERTABLE=>’ALL’
UPDATEABLE=>’’);

FND_DESCR_FLEX.UPDATE_DEFINITION(
/* Arguments that specify the flexfield location */
BLOCK=>’block_name’,
FIELD=>’field_name’,
/* Argument to enable or disable flexfield */
[ENABLED=>’{Y|N}’,]
/* Other optional parameters */
[VDATE=>’date’,]
[TITLE =>’Title’,]
[AUTOPICK=>’{Y|N}’,]
[USEDBFLDS=>’{Y|N}’,]
[READ_ONLY=>’{Y|N}’,]
[LOCK_FLAG=>’{Y|N}’,]
[HELP=>’APPL=application_short_name;
TARGET=target_name’,]
[CONTEXT_LIKE=>’WHERE_clause_fragment’}
1. Show message number for warn and error messages
2. Do not show messages.
3. Message naming standard is
       <prod_name>_<group_code>_<self_explanatory_message>
4. Assign 0 message number to the messsage if you wish not to display the prefix and the message number
5. custom message defined should be greater than 400,000
6. Use two messages to distinguish singular and plural token values
       e.g.,     One row updated.
                   &NUMBER_OF_ROWS rows updated.
                   [Two distinct messages]

Creating Row LOV

To display LOV on startup
At the end of WHEN-NEW-FORM- INSTANCE call

EXECUTE_TRIGGER('QUERY_FIND');


Implementing Row LOV


To implement a Row-LOV, create an LOV that selects the primary key of the row the
user wants into a form parameter, and then copy that value into the primary key field in the results block right before executing a query.

1. Create a parameter for your primary key
2. Create an LOV
3. Create a block level PRE-QUERY Trigger

               1. Set Execution Hierarchy Before
               2. Write the code

IF :parameter.G_query_find = 'TRUE' THEN
<Primary Key> := :parameter.<Your parameter>;
:parameter.G_query_find := 'FALSE';
END IF;

4. Create a Query Find Trigger

Finally, create a block-level user-named trigger QUERY_FIND on the results block
(Execution Hierarchy: Override) that contains:


APP_FIND.QUERY_FIND('<Your LOV Name>');