Showing posts with label Reports. Show all posts
Showing posts with label Reports. Show all posts

Monday, November 05, 2012

Enable SalesInvoice report on Enterprise Portal

Continuing the series of articles in SSRS, here I explain how to print the salesInvoice (or any other custom report) in Enterprise Portal.

Despite Packing Slip, this report is not supported in the standard Enterprise portal installation (you don't have the button to print an invoice on the EP invoices list page)

That's because Sales Invoice use a report controller that has not been implemented for the use in EP.

The solution I propose here is a little tricky, but it works pretty well :)

The key is to modify the class EPDocuGet that manages the download of reports or attachments from EP.

In that class you can write some code to print the SalesInvoice PDF to a temporary directory (how to do that is explained in a post before) and then write out the data in HTTP response of the Web request

So in the method run you can do something like:


 void run(Args args = null)  
 {  
   IISResponse       response = new IISResponse();  
 ;  
   // Transition to a server function to avoid  
   // Security problems  
   if (args)  
   {  
     if (args.record().TableId == tableNum(DocuRef))  
     {  
       EPDocuGet::runDocument(args.record().data(), response);  
     }  
     // Begin change  
     // Description:  
     else if (args.record().TableId == tableNum(CustInvoiceJour))  
     {  
       EPDocuGet::DWrunReportSalesInvoice(args.record().data(), response);  
     }  
     // End  
     else  
     {  
       EPDocuGet::runReport(args.record().data(), response);  
     }  
   }  
 }  

So if you got a CustInvoiceJour record you run your custom code. The method DWrunReportSalesInvoice is a copy of the runDocument method, a little bit modified:

 #define.BUFFER_SIZE(4096)  
 #File  
 client static void DWrunReportSalesInvoice(Common callerRecord, IISResponse response)  
 {  
   Query          query = new Query();  
   QueryBuildDataSource  qbds;  
   QueryRun        queryRun;  
   //EPSendDocument     document;  
   BinData         binData;  
   str           fileName;  
   int           fileOffset;  
   DictTable        table = new DictTable(callerRecord.TableId);  
   str           tempFileName;  
   boolean         emptyReport;  
   CustInvoiceJour     custInvoiceJour = callerRecord;  
   ;  
   if (EPDocuGet::hasTableAccess(callerRecord.TableId))  
   {  
     qbds = query.addDataSource(callerRecord.TableId);  
     if (callerRecord && callerRecord.TableId != tableNum(DocuRef))  
     {  
       // Requery the record to test record level security  
       qbds.addRange(table.fieldName2Id('RecId')).value(SysQuery::value(callerRecord.RecId));  
       query.recordLevelSecurity(true);  
       queryRun = new QueryRun(query);  
       if (queryRun.next())  
       {  
         //document = new EPSendDocument(callerRecord);  
         tempFileName = System.IO.Path::GetTempFileName();  
         EPDocuGet::DWPrintInvoicePdf(callerRecord, tempFileName);  
         infolog.clear();  
         //document.parmOriginal(true);  
         //document.parmFileName(tempFileName);  
         // Make document will run the report and send it to a PDF file with  
         // the path specified in tempFileName  
         //document.makeDocument();  
         fileName = custInvoiceJour.InvoiceId + ".pdf";  
         // remove all ';' from the filename. These are treated as delimiters by Ie  
         fileName = strReplace(fileName, ';', '_');  
         emptyReport = (WinAPI::fileSize(tempFileName) == 0);  
         response.clear();  
         binData = new BinData();  
         if (emptyReport)  
         {  
           response.contentType('application/Octet-Stream');  
           response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #txt + '"');  
           response.writeTxt(strFmt("@SYS58533", fileName));  
         }  
         else  
         {  
           response.contentType('application/pdf');  
           response.addHeader('Content-Disposition', 'attachment;filename="' + fileName + #pdf + '"');  
           // Loop over the stored file and chunk it down to the client  
           fileOffset = 0;  
           // Assert permission and get the temp filename  
           new FileIOPermission(tempFileName, #io_read).assert();  
           while(true)  
           {  
             // BP Deviation Documented  
             if (!binData.loadFile(tempFileName, fileOffset, #BUFFER_SIZE))  
             {  
               break;  
             }  
             fileOffset += #BUFFER_SIZE;  
             response.binaryWrite(binData.getVariant());  
           }  
           CodeAccessPermission::revertAssert();  
         }  
         binData = null;  
         WinAPI::deleteFile(tempFileName);  
       }  
     }  
   }  
 }  

And here is the method to print the invoice in PDF:

 client static void DWPrintInvoicePdf(Common _record, Filename filename)  
 {  
   args args = new args();  
   CustInvoiceJour custInvoiceJour = _record;  
   SRSPrintDestinationSettings printSettings;  
   SalesInvoiceController controller = new SalesInvoiceController();  
   str pdfPath = filename;  
   args.record(_record);  
   //pdfPath = WinAPI::getTempPath() + custInvoiceJour.InvoiceId + ".pdf";  
   // imposta nome report  
   controller.parmReportName(ssrsReportStr(SalesInvoice, Report));  
   // get print settings from contract  
   printSettings = controller.parmReportContract().parmPrintSettings();  
   // set print medium  
   printSettings.printMediumType(SRSPrintMediumType::File);  
   printSettings.fileFormat(SRSReportFileFormat::PDF);  
   printSettings.overwriteFile(true);  
   printSettings.fileName(pdfPath);  
   // forzo che non vengano cambiati i parametri di stampa che gli passo io  
   controller.DEVparmLockDestinationProperties(true);  
   // suppress the parameter dialog  
   controller.parmShowDialog(false);  
   controller.parmArgs(args);  
   // start operation  
   controller.startOperation();  
 }  


At this point, all you have to do is to create an Output Menu Item with the value "EPDocuGet" in the property "WebMenuItemName" and add this menu item to the EPCustInvoiceListPage form or whatever form you like.

Thursday, July 26, 2012

Print a SalesInvoice, PackingSlip or similar report to PDF in AX 2012

Printing a report in PDF in AX 2012 is pretty simple, but SalesInvoice report, or packing slip and similar seems not to work with the standard way.

That's because even if you pass printSettings parameters those are overriden by the controller class.

In AX 2009 there was a useful method called LockDestinationProperties in printSettings parameters that solve this problem, but this is gone in AX 2012.

So, If you want to reenable this feature, you have to do this:

Open the class SrsPrintMgmtFormLetterController and change those methods:


 void public abstract class SrsPrintMgmtFormLetterController extends SrsPrintMgmtController
{
    FormLetterReport formLetterReport;

    // Begin - Modify by lmattiuz on 27/06/2012
    boolean DEVLockDestinationProperties;
    SRSPrintDestinationSettings DEVfixedprintSettings;
    // End - Modify by lmattiuz
}

// Begin - Modify by lmattiuz on 27/06/2012 - Project: 120301_DevopmentTools_DEV
public Boolean DEVparmLockDestinationProperties(Boolean _DEVLockDestinationProperties = DEVLockDestinationProperties)
{
    DEVLockDestinationProperties = _DEVLockDestinationProperties;

    return DEVLockDestinationProperties;
}

protected void outputReport()
{
    // Begin - Modify by lmattiuz on 27/06/2012 - Project: 120301_DevopmentTools_DEV
    // Description:
    if(DEVLockDestinationProperties)
        formLetterReport.getCurrentPrintSetting().parmPrintJobSettings(DEVfixedprintSettings);
    // End - Modify by lmattiuz

    // execute report.
    if(formLetterReport)
    {
        formLetterReport.execute();
    }
}

public SysOperationStartResult startOperation()
{
    // Begin - Modify by lmattiuz on 27/06/2012 - Project: lmat_120301_DevopmentTools_DEV
    // Description:
    if(DEVLockDestinationProperties)
        DEVfixedprintSettings = this.parmReportContract().parmPrintSettings();
    // End - Modify by lmattiuz

    this.init();

    return super();
}       

Then you can print reports in PDF as you usually do:


 protected void printReportPdf(Common _record)
{
    args args = new args();
    CustInvoiceJour custInvoiceJour = _record;
    SRSPrintDestinationSettings printSettings;
    SalesInvoiceController controller = new SalesInvoiceController();

    args.record(_record);

    pdfPath = WinAPI::getTempPath() + custInvoiceJour.InvoiceId + ".pdf";

    // imposta nome report
    controller.parmReportName(ssrsReportStr(SalesInvoice, Report));

    // get print settings from contract
    printSettings = controller.parmReportContract().parmPrintSettings();

    // set print medium
    printSettings.printMediumType(SRSPrintMediumType::File);
    printSettings.fileFormat(SRSReportFileFormat::PDF);
    printSettings.overwriteFile(true);
    printSettings.fileName(pdfPath);

    // forzo che non vengano cambiati i parametri di stampa che gli passo io
    controller.DEVparmLockDestinationProperties(true);

    // suppress the parameter dialog
    controller.parmShowDialog(false);
    controller.parmArgs(args);

    // start operation
    controller.startOperation();
}