Saturday, August 06, 2011

Sending the Concurrent Request Output in Mail Attachment

     A Concurrent Program output cannot be sent as an attachment in the Oracle Application by itself. To implement this task find the steps.(Note: Most of the Scripts are designed for the Unix Based Systems).

  Normally the Concurrent Program output files are stored under the Directory: $APPLCSF/$APPLOUT and the all the Logfiles for the Same are stored under the $APPLCSF/$APPLLOG Directory. (For E.g. A Concurrent Request is submitted with it's number 2211122 then the output file generated under $APPLCSF/$APPLOUT as o2211122.out, irrespective of the format set at the concurrent request level and a log file is generated under $APPLCSF/$APPLLOG as l2211122.req)

Step 1:

      Write a concurrent Program and register as PDF (it will not work with the XML based reports, only the RDF based reports without as PDF can only be used.)

    Assume the XX_REPT1 is my concurrent program.

Step 2:

    Write a shell script as given below and regsiter as HOST file:

     a)  A Shell script by name XX_SENDMAIL.prog need to be   saved under the XX_TOP/bin directory.
     b) A Soft link to be created for $FND_TOP/$APPLBIN/fndcpesr to XX_SENDMAIL.
                   ln -sf $FND_TOP/$APPLBIN/fndcpesr XX_SENDMAIL

     c) Make sure the shell script has the 755 permissions.
   

     d) A Concurrent Program executable for XX_SENDMAIL need to be registered under Oracle Apps as HOST type.


      e) This Concurrent Program uses 5 default parameters internally, any any custom parameter will be used as fifth and above for the Shell script:


                    i)  First Parameter $0 : Program Name
                    ii) Second Parameter $1 : Username / Password
                   iii) Third Parameter $2 :  Apps User id
                    iv) Fourth Parameter $3 : Apps User Name
                     v) Fifth Parameter $4 :  Request ID


A Sample Shell Script to run any Shell script as a Concurrent Program is given below:



#------------------------------------------
outfile=$FND_TOP/$APPLOUT/o$4.out

echo '====================' > `echo $outfile`

  echo 'Program Name  :'$0 >> `echo $outfile`
  echo 'username/pwd  :' $1 >> `echo $outfile`
  echo 'apps user id :' $2 >> `echo $outfile`
  echo 'apps username:' $3 >> `echo $outfile`
  echo 'request id   :' $4 >> `echo $outfile`
  echo ------------------- >> `echo $outfile`
  echo 'Program arguments:' >>  `echo $outfile`
  echo ------------------- >> `echo $outfile`
#  shellscript arguments  start below :
  echo '$5= : '$5 >> `echo $outfile`
  echo '$6= : '$6 >> `echo $outfile`
  echo '$7= : '$7 >> `echo $outfile`
  echo '$8= : '$8 >> `echo $outfile`
  echo '$9= : '$9 >> `echo $outfile` 

#  shellscript commands can be entered below :
echo "Hello World " >> `echo $outfile`
echo '=====================' >> `echo $outfile`
#---------------------------------------------
 
  To send the mail from the Unix Servers, we can use many command line tools like mail,mailx,sendmail,mutt,pine etc. But some of the command line client tools need to be installed and some won't support to send attachment. mail and mailx  is the vastly used command line mail client and these can be used for without attachments or text based attachment mails.But not for the PDF based Attachment mails.

For eg:

mailx -s "Test mail"  xyz2abc.com< 1.txt

The above command embeds the contents of the text file into the mail. When we try to send the pdf file, then it embeds the junk characters in the body of email,as it doesn't have the encoding method. So, we need to encode this format which can be understandable by the Mail Servers to read the file as attachment.For which we need to use the uuencode command.

For Eg:

  uuencode file.pdf file.pdf | mailx -s "Test Mail as Attachment" xyz@abc.com

    The above command successfully sends a pdf format file as an attachment and it can be received by most recent Email Servers.But some exchange servers still can't understand this encoding and the file.pdf will be embedded inside the body of the mail will be seen with so many junk letters.

     To Overcome the above error, and after a brief research, found the sendmail command tool, with MIME encoding, uuencode to send a PDF attachment and the Body with HTML Code in a mail.The below shell Script can be used to send the pdf file attachment irrespective of the Mail Server(Gmail,Yahoo,MS Exchange etc)

To use a single shell script for all your concurrent requests, made a quite few changes in the above script and registration of the Concurrent Program with the set of following parameters:

 outfile=$APPLCSF/$APPLOUT/o$4.out <<< This will get the output file name for the current Shell script

echo '=====================================================' > `echo $outfile`

 echo 'Program Name  :'$0 >> `echo $outfile`   - Displays the Program name in Output file after completion of the program
 echo 'apps user id :' $2 >> `echo $outfile` 
 echo 'apps username:' $3 >> `echo $outfile`
 echo 'request id   :' $4 >> `echo $outfile`
 echo ------------------- >> `echo $outfile`
 echo 'Program arguments:' >>  `echo $outfile`
 echo ------------------- >> `echo $outfile`  



# There are 5 Parameters passed from the Script initiation PL/SQL Procedure to this Shell script
 echo ' email-id   :' $5 >> `echo $outfile`     
 echo 'request id   :' $6 >> `echo $outfile`
 echo 'subject   :' $7 >> `echo $outfile`
 echo 'att_name   :' $8 >> `echo $outfile`
 cp $APPLCSF/$APPLOUT/o$6.out $APPLCSF/$APPLOUT/o$6.pdf

PDFFILE=$APPLCSF/$APPLOUT/o$6.pdf
ATTNAME=$8
MAILFROM=oracle.alerts@arm.com.ng
SUBJECT=$7
MAILTO=$5
MAILBCC=$9  << This is the last parameter in the concurrent request, the email id in the last parameter can be set for Bcc or Cc.For CC just use MAILCC instead of MAILBCC>>
boundary="****"
{
echo  "From: $MAILFROM"
echo  "To: $MAILTO"
echo  "Bcc: $MAILBCC"
echo  "Subject:" $SUBJECT
echo "Mime-Version:1.0"${version}
echo "Content-Type:Multipart/mixed;boundary=Message-Boundary-"${boundary}
echo "--Message-Boundary-"${boundary}
echo "Content-type:text/html;charset=US-ASCII"
echo "Content-transfer-encoding: 7BIT"
echo "Content-Disposition:inline"
echo "Content-Description: Read Me First"
echo ""
echo "<html>
<head>
<title>HTML E-mail</title>
</head>
<title>HTML E-mail</title>
</head>
<body>
<p>Dear Sir/Madam,</p>
<p>&nbsp;</p>
<p>Please find the Attached Output File Details.</p>
<p>&nbsp;</p>
<p>Thanks and Regards,</p>
<p>Oracle Production Instance(XXX Company,Location)</p>

</body>
</html>"
echo ""
echo "--Message-Boundary-"${boundary}
echo "Content-type:Application/Octet-Stream;name=${PDFFILE};type=Binary"
echo "Content-disposition:inline;filename=${ATTNAME}"
echo "Content-transfer-encoding: X-UUencode"

echo "--Message-Boundary-"${boundary}
uuencode $PDFFILE $PDFFILE
}| /usr/lib/sendmail -t


     The above program can be used dynamically for any concurrent with the desired email-id's in TO,BCC and also a Subject.

    Register the above schell script as host executable and then register that executable to the desirec concurrent program with 4 Parameters:
    a) Email Address - Mandatory
    b) Request ID - Mandatory
    c) Subject - Mandatory
    d)Att_name - Mandatory
    e) Bcc_email - Optional

Let us register the concurrent Program with the shortname as XX_MAIL_SEND


Step 3:

     Now we need a master program to run the XX_REPT1 and XX_MAIL_SEND.  The logic inside this master concurrent program is :
  
   a) Submit the concurrent Program XX_REPT1
   b) Get the Request ID of the Concurrent request
   c) Check the Request ID is NULL or not
   d) IF not NULL then execute the check the PHASE_CODE of the above request
   e) LOOP the checking of PHASE_CODE until it compeltes
   f) If the STATUS_CODE is NORMAL then send initiate XX_MAIL_SEND program with the mandatory parameters.

Please find the Procedure of Master Program:

 CREATE OR REPLACE PROCEDURE apps.xx_conc_submit (
   errbuf    OUT   VARCHAR2,
   retcode   OUT   NUMBER
)
IS
   l_request_id     NUMBER;
   p_request_id   NUMBER;
   l_phase_code     VARCHAR2 (1);
   l_status_code    VARCHAR2 (1);
   l_date           VARCHAR2 (100);
BEGIN
   fnd_global.apps_initialize (fnd_profile.VALUE ('USER_ID'),
                               fnd_profile.VALUE ('RESP_ID'),
                               fnd_profile.VALUE ('RESP_APPL_ID'),
                               NULL,
                               NULL
                              );
   l_request_id :=
      fnd_request.submit_request (application      => 'XX',
                                  program          => 'XX_REPT1',
                                  description      => NULL,
                                  start_time       => NULL,
                                  sub_request      => FALSE
                                 );
   COMMIT;
   fnd_file.put_line (fnd_file.LOG,
                      'before loop l_request_id=' || l_request_id
                     );

   IF l_request_id IS NOT NULL
   THEN
----
      fnd_file.put_line (fnd_file.LOG,
                         ' Request Id inside IF :  ' || l_request_id
                        );

      SELECT phase_code
        INTO l_phase_code
        FROM fnd_concurrent_requests
       WHERE request_id = l_request_id;

      WHILE ('C' != l_phase_code)
      LOOP
         SELECT phase_code
           INTO l_phase_code
           FROM fnd_concurrent_requests
          WHERE request_id = l_request_id;
      END LOOP;

      fnd_file.put_line (fnd_file.LOG,
                         ' Phase_code after loop :  ' || l_phase_code
                        );

      SELECT status_code
        INTO l_status_code
        FROM fnd_concurrent_requests
       WHERE request_id = l_request_id AND phase_code = l_phase_code;

----
      IF (l_phase_code = 'C' AND l_status_code = 'C')
      THEN
         fnd_file.put_line (fnd_file.LOG, 'Inside IF' || l_phase_code);
         l_request_id :=
            fnd_request.submit_request
               (application      => 'XX
                program          => ' XX_MAIL_SEND',
                description      => NULL,
                start_time       => NULL,
                sub_request      => FALSE,
                argument1        => 'abc@gmail.com,def@zzz.com,kkk@zzz.com',
                argument2        => l_request_id,
                argument3        => 'Test Subject',
                argument4        => 'attachement_name.pdf',
                argument5        => 'bcc1@ddd.com,bcc2@ddd.com'
               );
      END IF;
   END IF;
END xx_conc_submit;

     Thanks for all the resources over web to get into this final code.My special thanks to Oracle Maestro Mr.Ezhilarasan,without him it might not had completed. All the Very Best

Wednesday, June 01, 2011

Configuring the Windows Printer on Linux Server using SAMBA and CUPS

Steps to configure :

1) Install the Printer at Windows Level
2) Install the Proper driver at Windows Level 
3) Check Printing from Local PC.
4) Share the Printer from Windows PC and give the permissions to the USER (e.g. printuser@abc.com and Password: print123) to print on this printer over the network.
5) Login as printuser@abc.com from another PC and connect to this Shared Printer and Print a TEST PAGE on this printer.
6) Make a note of the HOSTNAME or IP Address (Eg.10.2.1.1) of the Windows PC and also the Share Name.
7) In Linux, Printer either can be configured directly from the Printer configuration Screen or using CUPS over the web Interface(Remote or Local).
8) Access the CUPS URL from the browser.
9) Enter the Username and Password of the ROOT to Install the new Printer.
10) Click Add Printer ICON
11) Enter the Name of the Printer to Access from the Linux and Enter the Optional fields Location and Description and Click CONTINUE.
12) Select Windows Printer Via SAMBA.
13) The most critical part of the Configuration entering the DEVICE URI
                   Now we're configuring the WINDOWS BASED PRINTER over SAMBA with the credentials of the windows user, who has got the Permission to Print on this Printer.
In our Example:
Username : printuser
Password : print123
Domain: print123
IP Address of the PC : 10.2.1.1
Print Share Name(Case-Sensitive): HPLaserJ

URI for the above example can be : smb://printuser:print123@/10.2.1.1/HPLaserJ

Enter the URI and Continue
14) Select Make of the Printer : HP
15) Select the exact Printer Driver from the menu or submit the PPD file downloaded from the Manufacturers Site.
Click continue . This will conclude the Installation of the Printer.

Linux Based Printing configuration

     Configuring a Printer in Linux is easier,if you find the right driver to that Printer. If there is no proper Driver then we may use the Generic Driver, but it may not give the desired Output.
  
    In Red Hat Enterprise Linux 4 (RHEL 4), setuptool can be installed to configure and install an existing printer.By default the RedHat Linux comes with two different printing systems : LPRng and CUPS. 

LPRng :

To use the Printer Configuration Tool, it is must to be logged in as root.
Printer Configuration Tool can be started in 2 different ways:

i) In a graphical desktop environment, click Main Menu => System Settings => Printing.
ii) Type the command redhat-config-printer at a shell prompt (for example, in a command-line terminal window) to start the graphical version.Remember this command only works when DISPLAY variable is exported and the when you could able to access the GUI Screen of Linux

In case if the X server is not installed on Linux, and if you're looking for configuring the printer from text based screen then it can be either called from the setuptool or using system-config-printer-tui commnd. Which allows you to configure the Printer.

Internally the setuptool also calls  system-config-printer-tui comamnd. All the files related to setuptool are stored under the /etc/setuptool.d directory.

The Other System in Linux to Enable the Printing is CUPS.

Overview of CUPS

CUPS is the software you use to print from applications like the web browser you are using to read this page. It converts the page descriptions produced by your application (put a paragraph here, draw a line there, and so forth) into something your printer can understand and then sends the information to the printer for printing.
Now, since every printer manufacturer does things differently, printing can be very complicated. CUPS does its best to hide this from you and your application so that you can concentrate on printing and less on how to print. Generally, the only time you need to know anything about your printer is when you use it for the first time, and even then CUPS can often figure things out on its own.

How Does It Work?

The first time you print to a printer, CUPS creates a queue to keep track of the current status of the printer (everything OK, out of paper, etc.) and any pages you have printed. Most of the time the queue points to a printer connected directly to your computer via a USB or parallel port, however it can also point to a printer on your network, a printer on the Internet, or multiple printers depending on the configuration. Regardless of where the queue points, it will look like any other printer to you and your applications.
Every time you print something, CUPS creates a job which contains the queue you are sending the print to, the name of the document you are printing, and the page descriptions. Job are numbered (queue-1, queue-2, and so forth) so you can monitor the job as it is printed or cancel it if you see a mistake. When CUPS gets a job for printing, it determines the best programs (filters, printer drivers, port monitors, and backends) to convert the pages into a printable format and then runs them to actually print the job.
When the print job is completely printed, CUPS removes the job from the queue and moves on to any other jobs you have submitted. You can also be notified when the job is finished, or if there are any errors during printing, in several different ways.

After a above brief note, it can be concluded that the Major tasks performed by the linux System to print any document, it uses the CUPS as its interface. CUPS manages all the Print Documents and Queues.

How to Configure a Printer in Linux:

Before configuring the printer, it is necessary to look of the RPMS required to configure a Printer are available in the system or not.

Use the following command:

                 rpm -qa | grep cups

If the there are no rpms installed for cups, it is required to install the cups RPM from the Linux installation Disks.

All the commands used above to configure the printer, works well till Red Hat Enterprise Linux 4. But from the RHEL 5 printconf-tui has been deprecated.  

printconf-tui is no longs available in the RHEL 5. WHY???

In Red Hat Enterprise Linux there used to be a command line tool for importing and exporting CUPS configuration. In fact it was part of the printconf system: the previously-exported XML file would be imported into printconf’s own configuration, and printconf would then write new CUPS configuration based on that.
Red Hat Enterprise Linux 5 provides a re-written printing administration tool (still called system-config-printer), avoiding the many problems of the “separate configuration” approach. Now CUPS is configured directly using IPP, and this can be done remotely. The new system-config-printer tool does things in the same way as the CUPS web interface and the CUPS command line tools, and so they can all be used interchangeably.

MANAGING CUPS:

Often a print server will be installed with as little software as possible, and this means no graphical utilities. There are two ways to configure the CUPS server in this case: the most obvious one is to use the CUPS web interface on that machine. On a graphical desktop machine, point a web server to http://the-printer-server:631 and configure away.

The other way is to use system-config-printer on the desktop machine, but tell it to configure the print server’s CUPS instance rather than the one on the local machine (“Goto Server”). Just make sure to allow remote administration on the print server first; you can do that via the CUPS web interface.
The following steps can be used to configure the Printer using the CUPS web interface locally:

1. Download the PPD's of respective printers from their websites.
2. Su - root
3. mkdir /usr/share/cups/model/(Printer Manufacturer name)
4. cp *.ppd /usr/share/cups/model/foldername
5. service cups restart
6. Open the conqueror or mozilla
7. http://localhost:631
8. Click Administration tab
9. It prompts for user name & password(give root & its password)
10. Add printer
11. Give printer name (It should not contain space ,any special characters)
12. Enter location
13. Enter Descriptions
14. Device-Internet Printing Protocol
15. Device-URL-socket://hostname:9100 (Give the hostname of the printer)

The above only works if you have the X Display Server installed either with the GNOME or KDE.If you want to configure without KDE or GNOME, the best way is to configure using the CUPS Web Interface by accessing it remotely. But by default this feature is disabled, needs the following steps to configure and to enable this feature.
(Before Editing the cupsd.conf file, it is better to take a backup of this file)

1. Edit the cups configuration file by first running the following command on your server:

vi /etc/cups/cupsd.conf

2. Edit the file is to make the section that looks like:

# Only listen for connections from the local machine.
Listen localhost:631
Listen /var/run/cups/cups.sock

look like this:

# Only listen for connections from the local machine.
Port 631
Listen /var/run/cups/cups.sock

3. You then have to change the sections that looks like this:

< Location / >
# Restrict access to the server...
Order allow,deny
< /Location >
< Location /admin >
# Restrict access to the admin pages...
Order allow,deny
< /Location >
< Location /admin/conf >
AuthType Default
Require user @SYSTEM
# Restrict access to the configuration files...
Order allow,deny
< /Location >

to change like as follows:

< Location / >
# Restrict access to the server...
Order allow,deny
Allow all
< /Location >
< Location /admin >
# Restrict access to the admin pages...
Order allow,deny
Allow all
< /Location >
< Location /admin/conf >
AuthType Default
Require user @SYSTEM
# Restrict access to the configuration files...
Order allow,deny
Allow all
< /Location >

4. Finally, restart cups service:

service cups restart
     
 5. Now access the url from a remote server as:

http://yourservername:631

Note that when you change something, it may tell you that you need to add a certificate to firefox. Do so by clicking the add/get certificate button at the bottom of the firefox error message page. It will also tell you that to change stuff, you need to use the "https" version of the page instead of "http" so just go to:
https://yourserverip:631
You might also have to open/port forward port 631.

An addition would be that instead of doing "Allow from all", you can use "Allow from @LOCAL" and it restricts access to your local network. 

Wednesday, January 12, 2011

HR Workflow Process - Pending Even after the Process is Killed

As per Oracle, Oracle HR Leave of Absence SHOULD NOT be CANCELLED, but they should be REJECTED from the supervisor level. But practically, users always asks to close or cancel their Leave Workflow which is entered wrongly before their supervisor takes action against it. As a Workflow and System Administrator, this workflow process can be Killed or ended. Once this is done, all the notifications related to that Workflow will be Closed with FORCE. BUT if the user tries to create the leave again with the same dates sometimes there will be an error something like the dates are overlapping or leave of absence for this date is already.  The better approach to overcome this error to :


If you want to cancel a workflow, you have to do the following

-- Workflow Administrator

-- Status monitor

-- Search for workflow process

-- select a process and click on activity history

-- select the node "V5.0 Notify Approver with Correction" and click on skip

-- Select "Reject" in the pop list as result and apply.

The reason is , SSHR does not handle "cancel" action on a workflow process.


In case the workflow is already canceled and if the user wants to apply the leave for the same START DATE or his second of Leave of Absence is between those cancelled Leave Date then the Oracle HR LOA system thinks that the user applying for the LOA for the second time with in the same range of the Date and it will through an error and not allow the user to Apply the Leave. Even the Leave of Absence Screen shows the Previous Leave and with status PENDING FOR APPROVAL from their Supervisor.


This can be resolved in 2 steps:


1) Run the Complete Defunct HR Workflow Processes with the ITEMTYPE-HR and select all the default parameters. This should clear all the Workflow Status.


2) Even if the Problem is not resolved then need to perform the rollback the pending transaction from the back end.


Steps as follows:

-- query hr_api_transactions using creator_person_id, creation_date ,

process_name columns

-- note the the transaction_id for the cancelled transaction

now, call the following from back end :

execute hr_transaction_api.rollback_transaction

( p_transaction_id => sshr_transaction_id ,

 p_validate => false );

commit;

This removes the cancelled, hanging transaction.

A Handy script which will be very useful:


SELECT    'exec hr_transaction_api.rollback_transaction( p_transaction_id => '
       || hat.transaction_id
       || ', p_validate => false );'
  FROM hr_api_transactions hat, wf_notifications wn
 WHERE hat.item_key = wn.item_key AND wn.status = 'CANCELED'