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.
12 comments:
I tried this method and it had the following problem. when I create the output menuitem with Epdocuget as the webmenuitemname and added it to the EPCustinvoicelistpage , it says no object set on the output menuitem I created when I click it. Can you please advise what I am missing?
If you run it from inside Ax it's normal if you get an error message, this will work only from EP.
For the blank page, make sure your PDF is created correctly!
You could try creating a job that run the method EPdocuGet.DWrunReportSalesInvoice, so you can debug it and check if the PDF is created correctly.
You can even check the event viewer on the server that host the EP installation to see what errors are logged here!
And... what contain "DEVparmLockDestinationProperties"? I try run my report but always show in screen
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)
http://daxldsoft.blogspot.it/2012/07/print-salesinvoice-packingslip-or.html
Thank you very much, your blog is extraordinarily helpful!
Hello!
Is this a complete solution?
Because i have some problems...
When i click the button i added to the list page in EP i only get a blank page(I use IE). I try to run a job in AX 2012 where i Call EPDocuGet::DWPrintInvoicePdf(CustInvoiceJour, "\\\\space\\felles\\SalesInvoiceReport\\test.pdf") but i get an error.
there are some folders created in the Directory, but no pdf-files. what Method is responsible for creating the pdf, and what Method is responsible for showing it in EP?
best regards
Kent
Hi Kent, If the PDF is not created I think that you miss the part with the LockDestinationProperties.
There is a link on the article that explain how to do that:
http://daxldsoft.blogspot.it/2012/07/print-salesinvoice-packingslip-or.html
So, make sure the PDF is created correctly, and then everything should work.
BR
i tried running a job with code
select CustInvoiceJour where CustInvoiceJour.InvoiceId == "4484509";
EPDocuGet::DWPrintInvoicePdf(CustInvoiceJour, "c:\\EPSalesInvoicePDFtmp_"+custInvoiceJour.InvoiceId+".pdf");
and it created the PDF just fine.
I however still get a blank screen at downloaddocument.aspx after clicking the button in custTableListPage in EP...
Any ideas?
Thanks for your time.
regards
Kent, you should try to debug to understand where the problem lies.
If you can't debug from EP just put some throw error("some text"); around the method DWrunReportSalesInvoice to see what is going wrong.
That way should be easy to detect the error.
We've just found a solution the blank page problem. This was related to security and permission problems in our case. First, try running EP with the Microsoft Dynamics AX system admin role, and using the button. If that solves the problem then try adding permissions to your desired role, so that the methods involved in creating this report are allowed to be executed. This solved our blank page problem and got the button working.
Hey, this is working really good, but i was wondering if there's any way to get multiselection into the downloadDocument.aspx?
I have enabled for multiSelection in the listpage where i use the EPDocuget menu item and i can mark several records on the listpage running on EP, but the downloadDocument.aspx
only extract a single record in this code:
IAxaptaRecordAdapter record = tableContext.DataKey.GetRecord(session)
How can i get all of the marked records and maybe send them as a string in doc.runDownload(record) back to AX 2012 before i send them the documents?
I need this to make the user able to select multiple documents that i can stitch together to a single bigger PDF and send to the user...
Post a Comment