class RetailSharedParameters_Eventhandlers { /// <summary> /// Event handler for the "UploadFile" button click event. /// </summary> /// <param name="sender">The form control that triggered the event.</param> /// <param name="e">Event arguments.</param> [FormControlEventHandler(formControlStr(RetailSharedParameters, UploadFile), FormControlEventType::Clicked)] public static void UploadFile_OnClicked(FormControl sender, FormControlEventArgs e) { // Get the button that triggered the event FormButtonControl callerButton = sender as FormButtonControl; // Get the form run instance FormRun form = callerButton.formRun(); // Get the data source for the RetailSharedParameters table FormDataSource RetailSharedParameters_ds = form.dataSource(formDataSourceStr(RetailSharedParameters, RetailSharedParameters)) as FormDataSource; // Get the current record from the data source RetailSharedParameters RetailSharedParameters = RetailSharedParameters_ds.cursor(); // Prompt the user to upload a file FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult; // Check if the file upload was successful if (result && result.getUploadStatus()) { // Store the file name and download URL in the table RetailSharedParameters.FileName = result.getFileName(); RetailSharedParameters.SoundFile = result.getDownloadUrl(); // Save the changes to the database RetailSharedParameters.write(); } } /// <summary> /// Event handler for the "DownloadFile" button click event. /// </summary> /// <param name="sender">The form control that triggered the event.</param> /// <param name="e">Event arguments.</param> [FormControlEventHandler(formControlStr(RetailSharedParameters, DownloadFile), FormControlEventType::Clicked)] public static void DownloadFile_OnClicked(FormControl sender, FormControlEventArgs e) { // Variable to store the file URL str fileUrl = ''; // Get the button that triggered the event FormButtonControl callerButton = sender as FormButtonControl; // Get the form run instance FormRun form = callerButton.formRun(); // Get the data source for the RetailSharedParameters table FormDataSource RetailSharedParameters_ds = form.dataSource(formDataSourceStr(RetailSharedParameters, RetailSharedParameters)) as FormDataSource; // Get the current record from the data source RetailSharedParameters RetailSharedParameters = RetailSharedParameters_ds.cursor(); // Retrieve the stored file URL fileUrl = RetailSharedParameters.SoundFile; // Open the file URL in a browser if (fileUrl) { new Browser().navigate(fileUrl); } else { // Notify the user if no file URL is found warning("No file URL found."); } } }
Sherif Fayed
Wednesday, January 29, 2025
X++ Upload and Download file - D365 FO
Saturday, December 21, 2024
D365 Sending Email with Docentric Template for SalesInvoice.Report report as attachment using X++
public final class SendEmailHelper
{
public static str CCEmail, Esender;
public static LogisticsElectronicAddressLocator GetPrimaryEmail(AccountNum ACCNum)
{
if (!ACCNum)
{
throw error("Account number cannot be null or empty.");
}
DirPartyTable dirPartyTable = DirPartyTable::findRec(CustTable::find(ACCNum).Party);
if (!dirPartyTable)
{
throw error("No party found for the provided account number.");
}
LogisticsElectronicAddress logisticsElectronicAddress;
DirPartyLocation dirLocation;
select logisticsElectronicAddress
join dirLocation
where dirLocation.Location == logisticsElectronicAddress.Location &&
logisticsElectronicAddress.IsPrimary &&
dirLocation.Party == dirPartyTable.RecId &&
logisticsElectronicAddress.Type == LogisticsElectronicAddressMethodType::Email;
if (!logisticsElectronicAddress)
{
warning("No primary email address found.");
}
return logisticsElectronicAddress.Locator;
}
public static container getEmailTemplate(SysEmailId _emailId, LanguageId _languageId)
{
// Info(_emailId);
SysEmailMessageSYSTEMTable messageTable = SysEmailMessageSYSTEMTable::find(_emailId, _languageId);
SysEmailSYSTEMTable emailTable = SysEmailSYSTEMTable::find(_emailId);
if (!messageTable && emailTable)
{
// Try to find the email message using the default language from the email parameters
messageTable = SysEmailMessageSYSTEMTable::find(_emailId, emailTable.DefaultLanguage);
}
if (messageTable)
{
//CCEmail = emailTable.EmailId;
return [messageTable.Subject, messageTable.Mail, emailTable.SenderAddr, emailTable.EmailId];
}
else
{
warning("We didn't find a template"); // Let the user know we didn't find a template
return ['', '', emailTable.SenderAddr, emailTable.SenderName, emailTable.EmailId];
}
}
public static str Email_Body(CustInvoiceJour _custinvoicejour)
{
str InvoiceId = _custinvoicejour.InvoiceId;
str salesid = _custinvoicejour.SalesId;
str invoiceDate = date2str(DateTimeUtil::date(_custinvoicejour.InvoiceDate), 123,DateDay::Digits2,DateSeparator::Slash,DateMonth::Digits2,DateSeparator::Slash,DateYear::Digits4);
str customerName = CustTable::find(_custinvoicejour.InvoiceAccount).name();
str orderDate = date2str(DateTimeUtil::date(SalesTable::find(_custinvoicejour.SalesId).CreatedDateTime), 123,DateDay::Digits2,DateSeparator::Slash,DateMonth::Digits2,DateSeparator::Slash,DateYear::Digits4);
//str trackingNumber
RetailConfigurationParameters _RetailConfigurationParameters = RetailConfigurationParameters::findByName("INVOICED_TEMPLATE_ID");
str sub,tmp,Sender,frm;
str EmailId = _RetailConfigurationParameters.Value;
[sub,tmp,Sender,frm] = SendEmailHelper::getEmailTemplate(EmailId,'en-us');
Esender = sender;
tmp = strReplace(tmp,'%salesid%','%1');
tmp = strReplace(tmp,'%invoiceId%','%2');
tmp = strReplace(tmp,'%invoiceDate%','%3');
tmp = strReplace(tmp,'%customername%','%4');
tmp = strReplace(tmp,'%orderDate%','%5');
str ret = strFmt(tmp,salesid,InvoiceId,invoiceDate,customerName ,orderDate);
return ret;
}
public static void Sendmail(CustInvoiceJour _custinvoicejour)
{
System.Exception ex;
try
{
if (!_custinvoicejour)
{
throw error("CustInvoiceJour parameter is null.");
}
str invoiceId = _custinvoicejour.InvoiceId;
str body = SendEmailHelper::Email_Body(_custinvoicejour);
str emailTo = SendEmailHelper::GetPrimaryEmail(_custinvoicejour.InvoiceAccount);
if (!emailTo)
{
throw error("No email address found for the customer.");
}
SysMailerMessageBuilder builder = new SysMailerMessageBuilder();
builder.setBody(body);
builder.setFrom(Esender);
builder.addTo(emailTo);
builder.setSubject("Your order has been invoiced - " + invoiceId);
System.IO.Stream stream = SendEmailHelper::generateReportStream(_custinvoicejour.RecId);
if (stream)
{
builder.addAttachment(stream, "Your order has been invoiced - " + invoiceId + ".pdf");
}
else
{
warning("Stream for the report attachment could not be generated.");
}
SysMailerFactory::getNonInteractiveMailer().sendNonInteractive(builder.getMessage());
}
catch (Exception::CLRError)
{
ex = CLRInterop::getLastException();
throw error(ex.Message);
}
}
public static System.IO.MemoryStream generateReportStream(RecId invJournalRecId)
{
SalesInvoiceContract contract = new SalesInvoiceContract();
DocReportTemplate _DocReportTemplate ;
//Get Default Template to use from Docentric
select firstonly _DocReportTemplate
where _DocReportTemplate.Report == DOCREPORTTABLE::findReportId("SalesInvoice.Report").RecId
&& _DocReportTemplate.IsDefaultTemplate == NoYes::Yes;
//Get Invoice Record
CustInvoiceJour CustInvoiceJour = CustInvoiceJour::findRecId(invJournalRecId);
Filename fileName = _DocReportTemplate.TemplateId;
// Initialize the SalesInvoiceController
SrsReportRunController controller = new SrsReportRunController();
Args args = new Args();
// Attach the CustInvoiceJour record to the arguments
args.record(CustInvoiceJour);
controller.parmArgs(args);
// Set the report name
controller.parmReportName(ssrsReportStr(SalesInvoice, Report));
contract.parmRecordId(CustInvoiceJour.RecId);
controller.parmShowDialog(false);
controller.parmReportContract().parmRdpContract(contract);
// Use Docentric to generate the report
DocSrsReportGenerator docReportGenerator = new DocSrsReportGenerator(controller);
// Configure Docentric output settings directly in the generator
docReportGenerator.setPrintDestinationSettings_DocentricReport(DocOutputFileFormat::PDF, fileName);
// Generate the report as a container
container reportContainer = docReportGenerator.generateReport();
// Convert container to MemoryStream
System.IO.MemoryStream reportStream;
if (reportContainer)
{
reportStream = DocGlobalHelper::convertContainerToMemoryStream(reportContainer);
}
return reportStream;
}
}
Wednesday, July 24, 2024
D365 Sending Email with Customer Account Statement SSRS report as attachment using X++
public Email getCustEmail(CustAccount _custAccount)
{
CustTable custTable;
DirPartyLocation dirPartyLocation;
LogisticsLocation logisticsLocation;
LogisticsElectronicAddress logisticsElectronicAddress;
custTable = CustTable::find(_custAccount);
select firstonly Location, Party from dirPartyLocation
where dirPartyLocation.Party == custTable.Party
join RecId from logisticsLocation
where logisticsLocation.RecId == dirPartyLocation.Location
join Locator from logisticsElectronicAddress
where logisticsElectronicAddress.Location == logisticsLocation.RecId
&& logisticsElectronicAddress.Type == LogisticsElectronicAddressMethodType::Email
&& logisticsElectronicAddress.IsPrimary == NoYes::Yes;
return logisticsElectronicAddress.Locator;
}
Tuesday, July 23, 2024
clicking link on info message X++ to Open form
Message::AddAction() method can be used to embed an action within a message sent to the message bar. This method supports adding a single action that is associated with a display or action menu item, which is then visualized as a link button, redirecting users directly to the form with the correct record selected. Here's how it can be used.
public static void pushNotification(str NotificationMsg, str actionText,LedgerJournalTable journalTable) { MenuItemMessageAction actionData = new MenuItemMessageAction(); actionData.MenuItemName(menuItemDisplayStr(LedgerJournalTable)); actionData.TableName(tableStr(LedgerJournalTable)); actionData.RecId(journalTable.RecId); str jsonData = FormJsonSerializer::serializeClass(actionData); int64 messageId = Message::AddAction(MessageSeverity::Informational,NotificationMsg ,actionText, MessageActionType::DisplayMenuItem, jsonData); }Muhammad Aamir Hanif Reference
Thursday, November 30, 2023
D365 FO - Send Email with attachments by X++
Go to System administration >> Setup >> Email >> System email templates
Create New template
Monday, November 27, 2023
D365 FO Data entity Export using X++
Data entity Export using X++ in D365 FO
Export data entity through X++ in D365 FO.
public final class ExportEntity { public static void main(Args _args) { #dmf Query query; DMFEntityName entityName = "Batch groups"; SharedServiceUnitFileID fileId; // Update query // query = new Query(DMFUtil::getDefaultQueryForEntity(entityName)); query = new query(dmfutil::getDefaultQueryForEntityV3(entityname)); querybuilddatasource qbds = query.datasourcetable(tablenum(BatchGroupEntity)); sysquery::findorcreaterange(qbds, fieldnum(BatchGroupEntity, ServerId)).value("Batch:DEMO"); // Export file DMFDefinitionGroupName definitionGroupName = 'BatchGroupEntityExport'; try { DMFEntityExporter exporter = new DMFEntityExporter(); //There are optional parameters also added fileId = exporter.exportToFile( entityName, //Entity label definitionGroupName, //Definition group '', //ExecutionId group 'CSV', // or 'XML-Element',//Source format to export in #FieldGroupName_AllFields,//Specify the field group fields to include in export. query.pack(), //Query criteria to export records curExt(),// null, //List of XSLT files true, //showErrorMessages false); //showSuccessMessages if (fileId != '') { //Get Azure blob url from guid str downloadUrl = DMFDataPopulation::getAzureBlobReadUrl(str2Guid(fileId)); System.Uri uri = new System.Uri(downloadUrl); str fileExt; if (uri != null) { fileExt = System.IO.Path::GetExtension(uri.LocalPath); } Filename filename = strFmt('CustomerPaymentData%1',fileExt); System.IO.Stream stream = File::UseFileFromURL(downloadUrl); //Send the file to user File::SendFileToUser(stream, filename); // Below code will delete the export group. //DMFDefinitionGroup::find(definitionGroupName, true).delete(); } else { throw error("The file was not generated succefully. See execution log"); } } catch { throw error("DMF execution failed"); } } }
D365 FO Encryption And Decryption Using A Symmetric Key(AES) using X++
Encryption And Decryption Using A Symmetric Key(AES) using x++
Encryption And Decryption Using A Symmetric Key(AES) using x++.
I received a requirement to generate an XML file with encrypted data using a symmetric key. The recipients on the other side will decrypt the text using the same symmetric key. To test this, I used a dummy value such as 'RRR'.
To achieve this, I wrote the code in C# and added the resulting DLL to my project references.
C# Code:
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace EncryptionDecryptionUsingSymmetricKey { public class AesOperation { public static string EncryptString(string key, string plainText) { byte[] iv = new byte[16]; byte[] array; using (Aes aes = Aes.Create()) { aes.Key = Encoding.UTF8.GetBytes(key); aes.IV = iv; ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write)) { using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream)) { streamWriter.Write(plainText); } array = memoryStream.ToArray(); } } } return Convert.ToBase64String(array);// It will convert bytes to string } public static string DecryptString(string key, string cipherText) { byte[] iv = new byte[16]; byte[] buffer = Convert.FromBase64String(cipherText); // It will convert string to bytes
using (Aes aes = Aes.Create()) { aes.Key = Encoding.UTF8.GetBytes(key); aes.IV = iv; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (MemoryStream memoryStream = new MemoryStream(buffer)) { using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read)) { using (StreamReader streamReader = new StreamReader((Stream)cryptoStream)) { return streamReader.ReadToEnd(); } } } } } } }
X++ Code:
b14ca5898a4e4133bbce2ea2315a1916
Using EncryptionDecryptionUsingSymmetricKey; internal final class TestRunnableClass1 { public static void main(Args _args) { str key = "b65ff7654brt8799fghj4ed7892b6798"; str text = 'RRR'; str encryptedString = AesOperation::EncryptString(key, text); info(encryptedString); str decryptedString = AesOperation::DecryptString(key, encryptedString); info(decryptedString); } }
References Ref1 Ref2