Tuesday 7 May 2024

Creating and Consuming a .Net Library for SFTP Connection in Dynamics 365 Finance & Operations (Part-1)

Introduction

In today's interconnected systems, secure file transfers are critical. SFTP (Secure File Transfer Protocol), which utilizes SSH (Secure Shell) for enhanced security, is commonly used for this purpose. In this blog, I will guide you through creating a .Net library to establish an SFTP connection and demonstrate how to integrate this library into a Dynamics 365 Finance & Operations (D365FO) environment.

Step 1: Create a .Net Class Library

First, start by creating a .Net class library. This library will be responsible for handling the SFTP connection.

Step 2: Add Necessary NuGet Packages

For handling SFTP operations, add the following packages to your project:

  • Renci.SshNet – Provides the basic functionality for SFTP connections.
  • Microsoft.Bcl.AsyncInterfaces – Required for async support in .Net Standard 2.0 projects.

Note: You can install these packages via NuGet Package Manager or using the Package Manager Console.

Step 3: Implement SFTP Connection Logic

Implement the SFTP connection logic within your library. Create methods for connecting to the SFTP server, as well as for listing directories, downloading, and moving files.














Use the following code snippet for Getting directory, files and moves them after executing in the related folder.












Step 4: Build and Deploy the Library

After implementing the necessary functionality in your .Net library, build the project. Navigate to the bin\Debug or bin\Release folder, depending on your build configuration, and locate the generated DLLs. Select the highlighted DLLs from .Net project as shown below.



Step 5: Integrate with Dynamics 365 FO

To use your new library within Dynamics 365 FO, you need to import the DLLs into your project. Copy the DLLs from your .Net project's output folder to the AOSService->PackageLocalDirectory->Your Model Bin folder of your AX extension. This makes the library available to your AX project.








Step 6: Consume the Library in D365FO

Now, you can invoke the methods from your SFTP library within your D365FO codebase. You might need to handle any threading considerations, depending on how D365FO consumes external libraries.








Conclusion

By following these steps, you have created a reusable .Net library capable of handling SFTP operations and integrated it within Dynamics 365 FO, enhancing your application’s ability to interact securely with external systems through file transfers. This integration not only secures data transmission but also extends the functionality of your D365FO environment efficiently.

Saturday 4 May 2024

Fetching GST Amount from CustInvoiceLine in X++ D365 F&O

Recently, I was tasked with displaying the GST amount for a free text invoice. In my source code at the backend, I only had access to the CustInvoiceLine Table, while the GST amounts are stored in the TaxTrans Table. Initially, I struggled to find a direct relationship between these two tables, as multiple tables are needed to establish a relation. However, after some research, I discovered that the CustInvoiceLine already has an out-of-the-box method displayTaxAmount() which returns the GST amount.

Please see the screenshot below for more details.




Monday 1 April 2024

Key Updates in Dynamics 365 F&O for Version 10.0.39

Here’s a concise summary of the platform updates in Microsoft Dynamics 365 Finance & Operations version 10.0.39 (March 2024):


1- Additional Languages Available:

  • Six new languages are now accessible for user selection: Spanish (Bolivia), Spanish (Dominican Republic), Spanish (Ecuador), Spanish (Guatemala), Spanish (Peru), and Spanish (Venezuela). To set your preferred language, navigate to User options > Preferences > Language and country/region preference.

2- New Vendor Invoice Center:

  • A revamped workspace replaces the existing Vendor Invoice Automation workspace.
  • Provides an intuitive view of invoices at different processing stages.
  • Upcoming releases will introduce detailed drill-down lists and Copilot integration for exception handling.

3- Document Type Settings for Transferred Invoices:

  • Customers can now decide which document type to apply to transferred documents from Invoice Capture.
  • Document type settings can be configured across legal entities.

4- Default Financial Dimensions on Cost Invoices:

  • Default financial dimensions (Business unit, Cost center, and Department) from Invoice Capture now appear on the header of cost invoices.
  • Streamlines the invoice process and ensures correct approval routing.


Remember that some features may be available as part of a preview release, and the content is subject to change. For more details, refer to the official documentation.

Tuesday 12 March 2024

How to fix Error: "Common Language Runtime detected an invalid program" in D365FO

Recently, we upgraded our environment, which resulted in one of our customizations, previously working flawlessly, throwing the "Common Language Runtime detected an invalid program" error. During the debugging process, we identified a piece of code, to be the root cause of the error.

Error Screenshot:










Code Snippet Causing The Error:



Error Fix: To resolve this issue, I stored the result of DateTime::Now in a variable and then accessed the Ticks property from that variable. This approach eliminated the error, and the code now functions properly as it did before.





Note:
I understand the fix may seem unusual and nonsensical to some, but regardless, it worked. 😊

Wednesday 28 February 2024

Unlocking Worker Insights: Exploring Data Retrieval from Various Tables via HcmWorker in D365FO

During the development or customization in the Human Resource Module, we often required access to various tables' data to use in different functionalities. In this blog post, I've endeavored to consolidate all the relevant tables that provide data for the Human Resources module's displays and operations.

Note: The tables data below have been selected based on the HcmWorker table.

Get HcmWorker Table from Personnel Number: HcmWorker hcmWorker = HcmWorker::findByPersonnelNumber('00006');

Get Active HcmEmployment Table from HcmWorker Record Id: HcmEmployment hcmEmployment = HcmEmployment::getActiveEmploymentsByWorker(hcmWorker.RecId);

Get DirPerson Table from HcmWorker: DirPerson person = hcmWorker.DirPerson();

Get DirPersonName Table from DirPerson Record Id: DirPersonName dirPersonName = DirPersonName::find(person.RecId);

Get HcmPersonPrivateDetails Table from DirPerson Record Id: HcmPersonPrivateDetails personDetails = HcmPersonPrivateDetails::findByPerson(person.RecId);

Get HcmPositionWorkerAssignment Table from HcmWorker Record Id: HcmPositionWorkerAssignment positionWorkerAssignment = HcmPositionWorkerAssignment::getActivePositionWorkerAssignment(hcmWorker.RecId);

Get HcmPositionDetail Table from HcmPositionWorkerAssignment Position: HcmPositionDetail hcmPositionDetail = HcmPositionDetail::findByPosition(positionWorkerAssignment.Position);

Get HcmPositionHierarchy Table from HcmPositionWorkerAssignment Position: HcmPositionHierarchy positionHierarchy = HcmPositionHierarchy::findByPosition(positionWorkerAssignment.Position);

Get HcmPositionWorkerAssignment Table from HcmPositionHierarchy ParentPosition: HcmPositionWorkerAssignment parentPositionWorkerAssignment = HcmPositionWorkerAssignment::findByPosition(positionHierarchy.ParentPosition);

Get LogisticsPostalAddress Table from DirPerson Record Id: LogisticsPostalAddress logisticsPostalAddress = DirParty::primaryPostalAddress(person.RecId);

Get HRMCompFixedEmpl Table from HcmWorker Record Id and HcmPositionWorkerAssignment Position: HRMCompFixedEmpl fixedCompensation = HRMCompFixedEmpl::findMostRecentFixedCompensation(hcmWorker.RecId, positionWorkerAssignment.Position);

Get JmgEmployee Table from HcmWorker Record Id: JmgEmployee employee = JmgEmployee::find(hcmWorker.RecId);

Get HcmPersonDetails Table from DirPerson Record Id: HcmPersonDetails hcmPersonDetails = HcmPersonDetails::findByPerson(person.RecId);

Get HcmPositionType Table from HcmPositionDetail Position Type: HcmPositionType positionType = HcmPositionType::find(hcmPositionDetail.PositionType);

That's all for now. I hope you find this information helpful.

Creating and Consuming a .Net Library for SFTP Connection in Dynamics 365 Finance & Operations (Part-1)

Introduction In today's interconnected systems, secure file transfers are critical. SFTP (Secure File Transfer Protocol), which utilizes...