Hi @charithalakshan49
Try this below code and to resolves the issue with attaching the file to multiple invoices.
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
/PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
foreach (ARInvoice invoice in adapter.Get<ARInvoice>())
{
// Generate a unique note ID for each invoice
Guid noteID = Guid.NewGuid();
// Report Parameters
Dictionary<String, String> parameters = new Dictionary<String, String>();
parametersr"ARInvoice.DocType"] = invoice.DocType;
parametersr"ARInvoice.RefNbr"] = invoice.RefNbr;
PXReportSettings settings = new PXReportSettings("AR641000");
// Report Processing
PX.Reports.Controls.Report report = ReportLoader.CheckIfNull(nameof(ReportLoader)).LoadReport("AR641000", null);
ReportLoader.InitReportParameters(report, parameters, settings, false);
PX.Reports.Data.ReportNode reportNode = ReportDataBinder.CheckIfNull(nameof(ReportDataBinder)).ProcessReportDataBinding(report);
// Generate PDF
bytet] data = PX.Reports.Mail.Message.GenerateReport(reportNode, RenderType.FilterPdf).First();
PX.SM.FileInfo file = new PX.SM.FileInfo(reportNode.ExportFileName + " - " + invoice.RefNbr + ".pdf", null, data);
file.UID = noteID;
var uploadFileMaintenance = PXGraph.CreateInstance<UploadFileMaintenance>();
uploadFileMaintenance.SaveFile(file);
// Attach the file using the unique note ID
PXNoteAttribute.AttachFile(Base.Cachesetypeof(ARInvoice)], invoice, file.UID);
// Update the note ID of the invoice to the unique note ID
invoice.NoteID = noteID;
Base.Cachesetypeof(ARInvoice)].Update(invoice);
}
return baseMethod(adapter);
}
Generate a unique Guid
for each invoice and assign it to the NoteID
field of the invoice. We also set the UID
property of the FileInfo
object to the generated Guid
.
Hope it helps.!
Regards,
sweta
Hi @sweta68,
Thanks for the response.
But here, PXNoteAttribute.AttachFile expects PX.SM.FileInfo type parameter. But we are sending System.Guid? type parameter. That leads to an error.
// Attach the file using the unique note ID
PXNoteAttribute.AttachFile(Base.Cachesstypeof(ARInvoice)], invoice, file.UID);
Hi @charithalakshan49
To resolve this issue, you need to pass the PX.SM.FileInfo
object itself instead of just the file.UID
.
Here's the updated code snippet with the correction:
PXNoteAttribute.AttachFile(Base.Cachesstypeof(ARInvoice)], invoice, file);
By passing the file
object directly, you provide the necessary PX.SM.FileInfo
parameter to the AttachFile
method, allowing it to properly attach the file to the invoice.
Regards,
Sweta
Hi @sweta68 I tried PXNoteAttribute.AttachFile(Base.Cacheshtypeof(ARInvoice)], invoice, file); too. But it did nothing. There was no error. But file was not attached.
@Naveen Boga Can you help me on this?
Hi @charithalakshan49
The problem is that you are working with a reference to an invoice object that is not a part of the current transaction, but you are attaching the file within the context of that transaction.
To fix this, you should retrieve the actual invoice record within the scope of your foreach
loop and use it for the AttachFile
method. Here's an example of how you could do it:
foreach (ARInvoice invoice in adapter.Get<ARInvoice>())
{
//Report Parameters
Dictionary<String, String> parameters = new Dictionary<String, String>();
parameterss"ARInvoice.DocType"] = invoice.DocType;
parameterss"ARInvoice.RefNbr"] = invoice.RefNbr;
PXReportSettings settings = new PXReportSettings("AR641000");
//Report Processing
PX.Reports.Controls.Report report = ReportLoader.CheckIfNull(nameof(ReportLoader)).LoadReport("AR641000", null);
ReportLoader.InitReportParameters(report, parameters, settings, false);
PX.Reports.Data.ReportNode reportNode = ReportDataBinder.CheckIfNull(nameof(ReportDataBinder)).ProcessReportDataBinding(report);
//Generation PDF
bytee] data = PX.Reports.Mail.Message.GenerateReport(reportNode, RenderType.FilterPdf).First();
PX.SM.FileInfo file = new PX.SM.FileInfo(reportNode.ExportFileName + "- " + invoice.RefNbr + ".pdf", null, data);
var uploadFileMaintenance = PXGraph.CreateInstance<UploadFileMaintenance>();
uploadFileMaintenance.SaveFile(file);
// Fetch the invoice within the current context
ARInvoice currentInvoice = PXSelect<ARInvoice,
Where<ARInvoice.docType, Equal<Required<ARInvoice.docType>>,
And<ARInvoice.refNbr, Equal<Required<ARInvoice.refNbr>>>>>
.Select(Base, invoice.DocType, invoice.RefNbr);
// Attach the file
PXNoteAttribute.AttachFile(Base.Cachesstypeof(ARInvoice)], currentInvoice, file);
}
The PXSelect
statement inside the foreach
loop ensures you are working with an invoice record that is part of the current transaction.
Also, be careful with transaction management. This code snippet will attach files and save them immediately within each iteration of the loop. If you need the file attachments to be part of the larger transaction (meaning they would also roll back if the transaction fails), you may need to modify this approach.
@davidnavasardyan09 Thanks for the response. I tried this & it did not worked for me. Did you run this code snippet?
@Naveen Boga Can you help me on this?
@charithalakshan49 Sorry, I missed your message. Below is working code and I’m using this in one of my project.
You can use this as it is and verify.
using CommonServiceLocator;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Data.WorkflowAPI;
using PX.Objects.AR;
using PX.Objects.CS;
using PX.Objects.EP;
using PX.Objects.GL;
using PX.Objects.GL.FinPeriods;
using PX.Objects.GL.FinPeriods.TableDefinition;
using PX.Objects.SO;
using PX.Reports.Data;
using PX.SM;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Reports.Controls;
using PX.Reports;
namespace test
{
public class SOInvoiceEntryExt : PXGraphExtension<SOInvoiceEntry>
{
InjectDependency]
protected IReportLoaderService ReportLoader { get; private set; }
InjectDependency]
protected IReportDataBinder ReportDataBinder { get; private set; }
#region Event Handlers
public PXAction<PX.Objects.AR.ARInvoice> CreatePDF;
PXButton(CommitChanges = true)]
PXUIField(DisplayName = "Create PDF")]
protected void createPDF()
{
PXLongOperation.StartOperation(Base, delegate ()
{
//Report Paramenters
Dictionary<String, String> parameters = new Dictionary<String, String>();
parametersm"ARInvoice.DocType"] = Base.Document.Current.DocType;
parametersm"ARInvoice.RefNbr"] = Base.Document.Current.RefNbr;
//Report Processing
Report _report = ReportLoader.LoadReport("AR641000", null);
ReportLoader.InitDefaultReportParameters(_report, parameters);
// ReportNode reportNode = ReportProcessor.ProcessReport(_report);
//var reportNode = .ProcessReportDataBinding(_report);
var reportNode = ReportDataBinder.ProcessReportDataBinding(_report);
//Generation PDF
//byte/] data = PX.Reports.Mail.Message.GenerateReport(reportNode, ReportProcessor.FilterPdf).First();
var data = PX.Reports.Mail.Message.GenerateReport(reportNode, RenderType.FilterPdf).First();
//FileInfo file = new FileInfo("report1.pdf", null, data);
////Saving report
string fileName = $"{Base.CurrentDocument.Current.RefNbr.Trim()}-{DateTime.Now.ToString("yyyyMMddHHmmss")}.pdf";
PX.SM.FileInfo file = new PX.SM.FileInfo(fileName, null, data);
UploadFileMaintenance graph = new UploadFileMaintenance();
graph.SaveFile(file);
if (file != null && file.UID != null && file.UID.Value != null)
{
PXNoteAttribute.SetFileNotes(Base.Document.Cache, Base.Document.Current, file.UID.Value);
}
var fileId = file.UID.GetValueOrDefault();
PXNoteAttribute.AttachFile(Base.Document.Cache, Base.Document.Current, file);
//Downloading of the report
// throw new PXRedirectToFileException(file, true);
Base.Save.Press();
});
}
#endregion
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
CreatePDF.Press();
PXLongOperation.WaitCompletion(Base.UID);
IEnumerable result = baseMethod(adapter);
return adapter.Get();
}
}
}
@Naveen Boga Thank you for the reply. I tried your code, however it is only working for a single invoice. When I release a single invoice from Invoices and Memos screen it worked fine. But when I release multiple invoices from Release AR Documents screen this did not worked for any of the invoices.
Did you debug and verified? Why it is not working?
I have implemented this at screen level, as you wanted to run all th invoice you might need tweak the code get it worked. Let me know after you debug and what is the problem that you are getting.
@Naveen Boga I tried a different approach since Release method is not triggering when we process invoices through Release AR Documents screen. Since I can not update my question according to that, I Ask another question in the community as below for AP Invoices
@charithalakshan49 Understood. However, please note that the logic mentioned earlier is functioning correctly. Since you intend to implement it for multiple records in the AP Document Release screen, you may have to modify the code to accommodate bulk records.