Monday, November 8, 2021

Adding custom design in place of standard print management report in Dynamics 365 finance and operations

Please use below extensions to swap standard print management report to custom one.

//

/// Populates the PrintMgmtReportFormat table used for print management with the MyProject documents.

/// 

[ExtensionOf(classStr(PrintMgmtReportFormatPopulator))]

final class JPPrintMgmtReportFormatPopulator_Extension

{

    #ISOCountryRegionCodes

    #PrintMgmtSetup

    /// <summary>

    /// /Added new project invoice report

    /// </summary>

    protected void addDocuments()

    {

        this.addOther(PrintMgmtDocumentType::SIProjInvoice, ssrsReportStr(PSAProjInvoice, Report), ssrsReportStr(JPPSAProjInvoice, Report), #NoCountryRegionId);

        next addDocuments();

    }

}


///Print custom design in place of standard print managment report

/// <summary>

/// Event handler for <c>PrintMgmtDocumentType</c> class

/// </summary>

public class JPPrintMgmtDocType_EventHandler

{

    [SubscribesTo(classstr(PrintMgmtDocType),delegateStr(PrintMgmtDocType, getDefaultReportFormatDelegate))]

    public static void getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)

    {

        switch(_docType)

        {

            case PrintMgmtDocumentType::SIProjInvoice:

                _result.result(ssrsReportStr(JPPSAProjInvoice, Report));

                break;

        }

    }

}


Hope this helps!, I will come up with another interesting blog post.

Monday, October 18, 2021

Code snippet to convert string to memory stream in Dynamics 365 finance and operations

  public static System.IO.Stream JP_generateStreamFromString(str _text)

    {

        System.Byte[]           byteArray;

        System.IO.MemoryStream  memoryStream;


        byteArray    = System.Text.Encoding::UTF8.GetBytes(_text);

        memoryStream = new System.IO.MemoryStream(byteArray);


        return memoryStream;

    }


Hope this helps!, I will come up with another interesting blog post!



Wednesday, August 25, 2021

Get all the file names in List from blob container in Dynamics 365 finance and operations

 public static list getFileNamesFromBlob(CloudBlobContainer _blobContainer, str _filepath)

    {

        CloudBlobDirectory  cloudBlobDirectory;

        container           con;


        cloudBlobDirectory  = _blobContainer.GetDirectoryReference(_filepath);


        System.Collections.IEnumerable  lstEnumarable   = cloudBlobDirectory.ListBlobs(false, 0, null, null);

        System.Collections.IEnumerator  lstEnumarator   = lstEnumarable.GetEnumerator();

        List                            filenames       = new List(Types::String);

        

        while(lstEnumarator.MoveNext())

        {

            IListBlobItem   item = lstEnumarator.Current;

            

            if(item is CloudBlockBlob)

            {

                CloudBlockBlob  blob = item;

                blob.FetchAttributes(null, null, null);

                con = str2con(blob.name, '/');

                filenames.addStart(conPeek(con,conlen(con)));

            }

        }


        return filenames;

    }

Converting string to stream in Dynamics 365 finance and operations

 

/// <summary>

    /// Converts string to stream

    /// </summary>

    /// <param name="_record">

    /// String record to be converted to stream

    /// </param>

    /// <param name="_encoding">

    /// Encoding format

    /// </param>

    public static MemoryStream convertStringToStream(str _record, System.Text.Encoding _encoding)

    {

        System.Byte[]  byteArray =   new System.Byte[0]();


        if(_encoding == System.Text.Encoding::Unicode)

        {

            byteArray = System.Text.Encoding::Unicode.GetBytes(_record);

        }

        else

        {

            byteArray = System.Text.Encoding::ASCII.GetBytes(_record);

        }


        return  new MemoryStream( byteArray );

    }

Thursday, July 15, 2021

Email helper class to send email with attachment in Dynamics 365 finance and operations

Its very basic need from customers to send email with attachments for any implementation projects, hope the below helper class will be useful in this case.

/// <summary>

/// email helper class to send email with attachment

/// </summary>

public class EmailHelperClass

{

    public static boolean sendEmail(str _fromEMail, str _toEmail, sysEmailSubject _subject, str _body, str _ccEmail = "", FileName _filename ="", System.IO.Stream _stream = null)

    {

        System.Exception exception;

        try

        {

            var messageBuilder = new SysMailerMessageBuilder();

            messageBuilder.addTo(_toEmail)

                    .setSubject(_subject)

                    .setBody(_body);

       

            if (_ccEmail)

            {

                messageBuilder.addCc(_ccEmail);

            }

            if (_fromEMail)

            {

                messageBuilder.setFrom(_fromEMail);

            }

       

            if (_stream != null)

            {

                messageBuilder.addAttachment(_stream,_filename);

            }

            SysMailerFactory::sendNonInteractive(messageBuilder.getMessage());

        }

        catch (Exception::CLRError)

        {

            exception = CLRInterop::getLastException();

            info(strFmt("@SCM:EmailNotSentSetupInstruction", exception.ToString()));

        }

        return true;

    }

 

}

I will come with another interesting blog post!

Tuesday, July 13, 2021

Lookup Cache Property in Dynamics 365 finance and operations

 

Cache Lookup

result

None

No data is cached or retrieved from the cache for the table.
This property value should  not  be used, but would  be the use case for tables that are very up-to-date or where it is acceptable to read outdated data.

NotInTTS

When s  records  are selected  by a  Primary Key or a unique index,  the registry value  is cached when within   a transaction (after  ttsBegin). No cache scans made outside the transaction are used. When inside a transaction, the record is read once from the database and later from  the cache. The record  is locked by select when read in a transaction, which ensures that  the cached record is not updated when the transaction is active.

Found

When records are selected by a Primary Key or a unique index, the record value is cached for the duration of the if they are or until the record is updated. All "selects"  return the cache value if the record exists there.  Um "select for Update" in a transaction forces the database read and  replaces the cached record.
It is typically used for static  (lookup)tables,such as the Unit table, where records usually exist.

FoundAndEmpty

It has the same functionality as Found,except that if "select"does not return data,the absence of a record  is  cached. 
An example of  FoundAndEmpty  is the Discount  table , which by default has no records. Because "select"has not returned data,this information will be cached. Subsequent queries for the same nonexistent records  will return the cached value without reading from the database. A "select for Update" in a transaction forces the database to read and replaces the record in the cache.

EntireTable

The entire table is cached on the server as soon as at least one record is selected from the.
And a  cache setting is appropriate  for tables with a  known  number of limited records, such as parameter tables.


You can usually set the Lookup Cache of  a table according to the relationship  below,  however there   may be exceptions.

Table Group

Cache Lookup

Miscellaneous*

Do not use  and this Table Group  for custom tables.

Parameter

EntireTable

Group

Found

Main

Found

Transaction,
TransactionHeader
,and  TransactionLine

NotInTTS

Framework

Does not apply

Reference

Found

Worksheet,
WorksheetHeader,

and WorksheetLine

NotInTTS

Hope you find this helpful and will come up with another interesting blog post!


Table Group Property in Dynamics 365 finance and operations

 

Table Group

description

Examples

Framework

Tables that are used by the underlying Dynamics 365 FOframeworks,such as Workflow. These tables are typically created during installation and are not associated with configuration  keys.

NumberSequenceTable,
WorkflowElementTable

Group

Tables used to categorize the tables that are in the Table Group:  Main.

CustGroup,
VendGroup

Main

Master or master tables that contain data for a central business object. These tables typically contain basic and static information.

CustTable,
VendTable

Miscellaneous

Tables that do not fall into any of the other categories. This is the default value in a new table. Avoid using this  Table Group.

TableExpImpDef

Parameter

Tables that contain data used primarily as parameters or configuration information for one of the main tables (a table that has  the  Table Group:  Mainproperty).
Tables that typically  contain only one record per company.

CustParameters,
VendParameters

Reference

Tables that contain reference data.

ExchangeRate,
FiscalCalendar

Transaction, Transaction
Header,  
and  TransactionLine

Tables that contain d dataand transactions.
These tables  are not used for data entry directly.
A  TransactionHeader table  categorizes  the information from the tables  that are in the Table Group:  TransactionLine.

CustTrans,
VendTrans

Worksheet, Worksheet
Header,  
and  WorksheetLine

Tables that contain information that will be validated and transformed into transactions.
A  WorksheetHeader table  categorizes the information of the tables that are in the Table Group:  WorksheetLine.
Compared to the data contained in a Transaction table, the data in the  Worksheet tables is temporary and can be deleted without affecting system stability.

SalesTable,
SalesLine

Dynamic name for any electronic report format in Dynamics 365 finance and operations

 I would like to show, how can we give dynamic name for any format in electronic reporting known as GER. 

Its very common requirement from customer to have meaningful and dynamic name for formats. its very simple configuration.

Lets take ISO20022 Credit transfer file in this example, please select the derived format and click on designer of format. 

Then select XMLHeader and click on Mapping. down we can see file name which comes default when we generate report. the same can be generated based on the available in model.


Click on Edit icon and write name you would like to have, here I have just appended current system date.



Save the changes and close designer window then check by generating file.


That's all if you generate ER file then we can see customized name for file. hope you find this helpful , I will come up with another interesting blog!

Use constant variable in place of Macros in Dynamics 365 finance and operations

Macros functionality was  originally a bug in implementing the legacy  compiler,  however, many developers often take advantage of this functionality.   Dynamics  365 FO  includes the use of  Macros, but Microsoft recommends that new codes not be  written  using  Macros.   This functionality has a significant effect on compiler performance.

Therefore, use the concepts of constant variables(const)and read-only (readonly) instead of Macros.

Remembering that constant variables, the value cannot be changed, and read-only variables can be declared in class constructors (method:  new)only.

Hope you find this useful I will come up with another interesting blog post!




Exception handling (Try / Catch ) blocks use in Dynamics 365 finance and operations

Use the throw,  try... catch,  finally,   and retry  to generate  and handle exceptions.

In transaction developments(ttsbegin/ttscommit),use the  exception  presented below:  

·        Deadlock -  Handling for deadlocks in the  database. The deadlock occurs  when multiple transactions are waiting for each other.

·        UpdateConflict -  Handling for UpdateSConflicts. The update conflict occurs  when a transaction is using OCC (Optimistic Concurrence Control). The transaction can be repeated.

·        DuplicateKeyException -  Handling for duplicate key field conflicts. Duplicity occurs when a transaction is using Optimistic Concurrence Control (OCC). The transaction can be repeated.


    #OCCRetryCount

    try

    {

ttsbegin;

        Your code here

        ttscommit;

    }

    catch (Exception: :D eadlock)

    {

        Retry on deadlock

        retry;

    }

    catch (Exception::UpdateConflict)

    {

        Retry to resolve conflict update

if (appl.ttsLevel() ==  0)

        {

            if (xSession::currentRetryCount() >= #RetryNum)

            {

                throw Exception::UpdateConflictNotRecovered;

            }

            else

            {

                retry;

            }

        }

        else

        {

            throw Exception::UpdateConflict;

        }

    }

    catch(Exception: :D uplicateKeyException)

    {

        Retry in case of a duplicate key conflict

if (appl.ttsLevel() ==  0)

        {

            if (xSession::currentRetryCount() >= #RetryNum)

            {

                throw Exception::D uplicateKeyExceptionNotRecovered;

            }

            else

            {

                retry;

            }

        }

        else

        {

            throw Exception::D uplicateKeyException;

        }

    }

Hope you find this useful, I will come up with another interesting blog post.