Solved

How to get the PDF from an IFS-generated report?


Userlevel 6
Badge +12

Hello,

I would like to be able to print one of the “main” IFS reports to PDF and be able to access the PDF -- from outside of IFS. For example, I would like to be able to print a Purchase Order and have access to the generated PDF, from a custom-build .NET program (C#).

I turned on the debugger in IEE, and after the popup comes up to print, preview, or email the Purchase Order, there is no output in the debugger. So, I cannot tell what is being called to generate the PDF. But the Windows IEE client must be telling Oracle what to do in order for the PDF to be created, no?

The bottom line is that I would like to use Oracle package method calls to generate and access the PDF representing a document such as this. I don’t want to re-create the whole purchase order report outside of IFS when the default P.O. is already a good start, and the PDF format is acceptable.

How to I generate a PDF and access it from outside IFS via Oracle API calls?

 

Thanks,

Joe Kaufman

icon

Best answer by malik.sally 16 July 2021, 07:20

View original

This topic has been closed for comments

10 replies

Userlevel 5
Badge +10

You may want to use report rules and save the PDF in an FTP or Shared folder and use it? I’ve done that many times in the past.

Userlevel 6
Badge +12

You may want to use report rules and save the PDF in an FTP or Shared folder and use it? I’ve done that many times in the past.

 

Thanks, malik.sally. I am not sure what you are referring to, though. Is there some way of sending output consistently to a known location and grabbing it from there? How would I trigger a write to that file from outside of IFS?

 

Thanks,

Joe Kaufman

Userlevel 5
Badge +10

I am not sure whether I understand you correctly, By setting up a report rule  similar to the following, will save the PDF version of the report in FTP / Shared Folder. A fixed location with the file name varying depending on the order no / supplier id / system date etc.

 

 

if you can tell the original requirement, there may be a way to handle it.

Userlevel 6
Badge +12

OK, remember you asked for it.  *smile*

The original requirement is pretty simple, and we already have it working in legacy applications: We want to have a document (like a Purchase Order) print as a PDF, then display in the end-user's email client (Outlook, in this case) as an attachment. The email should also have address recipients filled in and pre-defined text already placed in the email body.

Here is the tricky bit -- we want to then display that composed email for the user so they can modify the body, change recipients, or even attach additional documents to the email. These are business requirements and are not negotiable, These requirements are not workarounds or poorly-modeled workflows -- they are how our users work and how we maintain an edge in customer service and supplier relations.

In current applications we have complete control over document generation, supplemental data look-ups, and email (Outlook) automation. We generate PDFs then use COM automation to automate Outlook into composing an email and displaying it for the user (or just sending it, if it requires no user interaction). We send thousands of emails in this way, from internal alerts to outward-facing notifications. Over 100,000 emails were generated and sent in this fashion in 2020, with around 25,000 of those being the type that displayed for the user so they could perform additional operations before clicking "Send".

IFS does not allow this particular type of emailing, as far as we can find. IFS is good at sending pre-built emails to pre-defined addresses. It is good at generating PDF documents. It can even perform certain operations with the client email application. But it cannot put all the things together that I mention above, unless we are missing something. Here is a more concise summary of requirements:

  1. Generate a PDF of a document in IFS, such as a Purchase Order.
  2. Attach that generated PDF to a newly-composed email in Outlook.
  3. Fill in some default email recipients for the composed email.
  4. Place a default snippet of text in the email's body. (The snippet could be different for every composed email, so we cannot use signatures for this.)
  5. Display the email for the end-user so they can make further modifications before sending. These modifications might include personalizing the body of the email, adding an email recipient, or attaching additional documents.

Due to the client-side nature of these requirements, I am prepared to do all of the above via a custom program (.NET, C#) that has access to IFS and access to the Outlook automation we require. The Outlook automation already exists, in fact, as does IFS data access (this is also my migration application). But automating Outlook will only work if I can also generate the document I need to attach to the email before displaying it. If I can get it all working I can call the application from a RMB custom menu option hanging off the appropriate IFS page.

Report Rules: There is some potential there. If I set up a rule to send a PDF to a known, shared network location I could create PDFs on demand, wait for the file, then attach it. But even with a rule in place, how do I trigger the generation of the report so that the rule is invoked? IEE is not showing me anything I can use with regard to understanding how to trigger document generation from outside IFS. Scheduled tasks are another thought I had, as I already have API code to invoke a scheduled task on demand. But I am not sure about invoking a scheduled task for a specific set of parameters (e.g. for a certain Purchase Order number).

Any ideas on how to do this are very welcome! I am going to head over to Aurena and turn on logging and print a Purchase Order from there, as sometimes Aurena shows more of what is going on behind the scenes.

Thanks,
Joe Kaufman

Userlevel 5
Badge +10

Ha ha! I asked for it ;). In fact I had a similar requirement at one of our customer and we are in the process of providing a solution.  I know I am not answering your question but thought I will share my experience so you can get some ideas.

The requirement was to create a draft email in MS Outlook with the PDF file of the PO report and any connected documents (IFS Doc Revs on PO Header, Part line and no part lines) as well as prefill data for the “To Address”, “Subject” etc. This gives the user the option to add extra info in the mail body / add recipients / add more documents before sending the email.

Currently development is in progress to create a customized action (IFS Aurena equivalent to a Right Mouse Button Menu).

The solution we provided is as follows;

  1. The Customized Action / Menu to generate PDF and attach the created PDF as a Document Revision within IFS Applications and connect it to the Purchase Order Header. This was achieved with the standard print purchase order to a specific logical printer with a report rule attaching the generated purchase order pdf to the purchase order header.
  2. Customized Action / Menu fetching all the connected document revisions and generating the draft email. Note: we are having challenges in attaching multiple documents via this in IFS Aurena as the Aurena Agent / Framework only supports one attachment. Currently the modification works with one file.

Ideally we wanted the above to actions to be in one go, but due to the fact that the pdf is generated and attached via a batch job, a delay between item 1 and 2 makes it impossible to get it seamless.

Userlevel 6
Badge +12

Ha ha! I asked for it ;). In fact I had a similar requirement at one of our customer and we are in the process of providing a solution.  I know I am not answering your question but thought I will share my experience so you can get some ideas.

The requirement was to create a draft email in MS Outlook with the PDF file of the PO report and any connected documents (IFS Doc Revs on PO Header, Part line and no part lines) as well as prefill data for the “To Address”, “Subject” etc. This gives the user the option to add extra info in the mail body / add recipients / add more documents before sending the email.

Currently development is in progress to create a customized action (IFS Aurena equivalent to a Right Mouse Button Menu).

The solution we provided is as follows;

  1. The Customized Action / Menu to generate PDF and attach the created PDF as a Document Revision within IFS Applications and connect it to the Purchase Order Header. This was achieved with the standard print purchase order to a specific logical printer with a report rule attaching the generated purchase order pdf to the purchase order header.
  2. Customized Action / Menu fetching all the connected document revisions and generating the draft email. Note: we are having challenges in attaching multiple documents via this in IFS Aurena as the Aurena Agent / Framework only supports one attachment. Currently the modification works with one file.

Ideally we wanted the above to actions to be in one go, but due to the fact that the pdf is generated and attached via a batch job, a delay between item 1 and 2 makes it impossible to get it seamless.

 

Thank you so much for taking the time to read my lengthy email and explain the customization you are performing -- it aligns well with what we are trying to do! Client-side operations are (naturally) more difficult with a platform like IFS, we are finding.

If I may ask one more question/clarification: For your Step 1, that means a purchase order header will always have a document attached to it, a somewhat redundant document, since at any point you could print a working copy of the PO, yes? It would mean any time a user previews an email for the PO (or in your case, creates a draft), another document (or revision) is created and stored as a BLOB in Oracle. Does this make data size issues a problem? When generating the document to attach to the P.O. header, does that also create a copy of the report in the Report Archive, taking even more space? Granted, these PDFs are generally fairly small, but still...

Once a document is created I can pull any number of documents and any amount of additional data via my custom application written in C#, so multiple attachments would not be an issue in my case -- that part is already available for use. It is the document creation that is tricky. This is certainly a great approach, though, as long as it doesn't bloat our LOB tablespaces with redundant data. If we did this, we could probably just create the document immediately any time the P.O. was saved, and that could potentially create a lot of documents/revisions. Alternately, it would be two RMB menu options, one to "Create PO Hard-Copy & Attach To PO", then one to, "Preview Email Draft" that would attach the document to the email. Am I correctly understanding the approach you are taking?

Again, thank you so much for taking the time -- you have my brain humming with some "Friday Fun" projects I can try to make this work! have a great weekend!

Thanks,
Joe Kaufman

Userlevel 6
Badge +12

Wanted to mention one more thing…

I checked the report archive today and found the PDF_ARCHIVE view. It has the BLOBs containing the actual PDF documents, so is exactly what I need. And while it isn’t as strongly linked to Purchase Orders (only via the “Notes” field), it still works. One can even look at the XML_REPORT_DATA view to get data related to the printed PDF.

I am curious, then, as to why you are going with linking the PDF as a DocMan document when printing the PDF to the archive could serve the same purpose? Is that because a linked document is easier to manipulate with IFS Connect, etc.? 

For my (completely custom-programmed) needs, the archive will work fine, and if we can figure out how to automatically create the report archive, it could even be a single-step process.

Thanks again for all your help!

 

Joe Kaufman

Userlevel 5
Badge +10

This customer has a requirement where they want to select and attach part/all of the documents attached to the purchase order to be sent along with the PO Layout in an email. In order to handle that we have created a “connected documents’ tab on the PO screen and added a column so the user can select a check box “to be emailed” on the document that they want to attach to the mail. Thus we used the same logic to silently print the PO, attach to the PO, and automatically select the ‘to be emailed’ check box.

Userlevel 6
Badge +12

This customer has a requirement where they want to select and attach part/all of the documents attached to the purchase order to be sent along with the PO Layout in an email. In order to handle that we have created a “connected documents’ tab on the PO screen and added a column so the user can select a check box “to be emailed” on the document that they want to attach to the mail. Thus we used the same logic to silently print the PO, attach to the PO, and automatically select the ‘to be emailed’ check box.

 

Sounds slick, and I can see why you would want DocMan involved for that. We might get to that point in the future.

You don’t happen to know how to force generation of an archived PDF for a PO, do you? Have you linked PDF generation to a Custom Event that fires any time the PO is changed, or do you simply inform the user that they need to preview the PDF first, then run your emailing code? If the latter, do you force them to preview it through normal IFS dialogs, or do you have code that generates the PDF behind the scenes without forcing the user through the print screen? I am close to having the email preview working, but it will only work if at least one PDF has been generated for the PO (it grabs the most recent PDF by result key, and displays a popup for the user if no PDFs are found).

Thanks for taking the time to talk through all this with me -- great progress is being made! Let me know if there is anything I can help you with in return!

 

Thanks,

Joe Kaufman

Userlevel 6
Badge +12

Hello,

For closure on this, I am posting my final solution.

I now have this working as a single Custom Menu option that calls a custom-developed, in-house WinForms application (written in C#) that generates a PDF for a Purchase Order, grabs the PDF from the archive, and attaches it to an email (Outlook client). The composed email is then displayed for the user to further modify and send.

The second part -- grabbing the PDF from the archive -- is a simple matter of pulling the BLOB contents from the PDF_ARCHIVE data object and streaming it to a file.

For the first part -- generating the PDF for the Purchase Order -- I added a custom method to a PL/SQL API package we have already created to house special routines unique to our company. I created the API method from code presented here on other threads, so much thanks to everyone who has contributed to those discussions! Here is the final package body procedure that takes in a purchase order number to generate a PDF in PDF_ARCHIVE. It also returns the result key as an output parameter:

PROCEDURE GeneratePurchaseOrderPDF (order_no_ IN VARCHAR2, result_key_ OUT NUMBER) AS
report_id_ VARCHAR2(2000) := 'PURCHASE_ORDER_PRINT_REP';
layout_name_ VARCHAR(2000) :='PurchaseOrderPrintRep.rdl';
printer_id_ VARCHAR2(2000) := 'PDF_PRINTER';
pur_order_print_option_ VARCHAR(2000) := 'Order';
report_attr_ VARCHAR2(2000) := '';
parameter_attr_ VARCHAR2(2000) := '';
distribution_list_ VARCHAR2(2000) := '';
instance_attr_ VARCHAR2(2000) := '';
print_job_id_ VARCHAR2(2000) := '';
print_attr_ VARCHAR2(2000) := '';
attr_ VARCHAR2(2000) := '';
BEGIN
-- Set report attributes.
Client_Sys.Set_Item_Value('REPORT_ID', report_id_, report_attr_);
Client_Sys.Set_Item_Value('LAYOUT_NAME', layout_name_, report_attr_);
-- Set parameter attributes.
Client_Sys.Set_Item_Value('ORDER_NO_LIST', order_no_, parameter_attr_);
Client_Sys.Set_Item_Value('PUR_ORDER_PRINT_OPTION', pur_order_print_option_, parameter_attr_);
-- Prepare Archive and client report.
Archive_API.New_Client_Report(result_key_, report_attr_, parameter_attr_, distribution_list_, print_attr_);
Archive_API.Get_Info(instance_attr_, parameter_attr_, result_key_);
-- We are now ready to assemple final attributes, create the Print Job, and execute it.
Client_Sys.Set_Item_Value('PRINTER_ID', printer_id_, attr_);
Print_Job_API.New(print_job_id_, attr_);
Client_Sys.Set_Item_Value('PRINT_JOB_ID', print_job_id_, instance_attr_);
Client_Sys.Set_Item_Value('RESULT_KEY', result_key_, instance_attr_);
Print_Job_Contents_API.New_Instance(instance_attr_);
Print_Job_API.Print(print_job_id_);
dbms_output.put_line('Purchase Order PDF generation successful. Result Key = ' || result_key_);
END GeneratePurchaseOrderPDF;

 

The above subroutine has no error handling, so when called from C# any error will come back as a full Oracle stack dump (which is probably OK for most use cases). I am also going to build in a couple pre-checks to make sure the Purchase Order exists and that it is not in a Planned, Stopped, or Cancelled state. The method will error out anyway if an order is in Planned or Cancelled state, but allows PDF generation for a Stopped (frozen) order. I figure I may as well check everything I can in my C# program so I can more elegantly handle problems that arise.

In summary, the C# program will call the above API method, and if it is successful it will use the returned result key to grab the PDF from the report archive. This will represent an up-to-date copy of the Purchase Order to attach to an email and present to the user.

Thank you, malik.sally, and everyone else on the Community threads that helped me deliver this solution!


Thanks,
Joe Kaufman