Book Image

Dynamics 365 for Finance and Operations Development Cookbook - Fourth Edition

By : Abhimanyu Singh, Deepak Agarwal
Book Image

Dynamics 365 for Finance and Operations Development Cookbook - Fourth Edition

By: Abhimanyu Singh, Deepak Agarwal

Overview of this book

Microsoft Dynamics 365 for Finance and Operations has a lot to offer developers. It allows them to customize and tailor their implementations to meet their organization’s needs. This Development Cookbook will help you manage your company or customer ERP information and operations efficiently. We start off by exploring the concept of data manipulation in Dynamics 365 for Operations. This will also help you build scripts to assist data migration, and show you how to organize data in forms. You will learn how to create custom lookups using Application Object Tree forms and generate them dynamically. We will also show you how you can enhance your application by using advanced form controls, and integrate your system with other external systems. We will help you script and enhance your user interface using UI elements. This book will help you look at application development from a business process perspective, and develop enhanced ERP solutions by learning and implementing the best practices and techniques.
Table of Contents (18 chapters)
Title Page
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Customer Feedback
Dedication
Preface

Copying a record


Copying existing data is one of the data manipulation tasks in Dynamics 365 for Finance and Operations. There are numerous places in the standard D365 application where users can create new data entries just by copying existing data and then modifying it. A few of the examples are the Copy button in Costmanagement | Inventoryaccounting | Costingversions and the Copy project button in Projectmanagement and accounting | Projects | All projects. Also, although the mentioned copying functionality might not be that straightforward, the idea is clear: the existing data is reused while creating new entries.

In this recipe, we will learn two ways to copy records in X++. We will discuss the usage of the table's data() method, the global buf2buf() function, and their differences. As an example, we will copy one of the existing ledger account records into a new record.

How to do it...

Carry out the following steps in order to complete this recipe:

  1. Navigate to General ledger | Chart of accounts | Accounts | Main accounts and find the account to be copied. In this example, we will use 130100, as shown in the following screenshot:
  1. Create a Dynamics 365 for Operations Project, create a runnable class named MainAccountCopy with the following code snippet, and run it:
        class MainAccountCopy 
       {         
         /// <summary> 
         /// Runs the class with the specified arguments. 
         /// </summary> 
         /// <param name = "_args">The specified arguments.</param> 
         public static void main(Args _args) 
        { 
          MainAccount mainAccount1; 
          MainAccount mainAccount2; 
 
          mainAccount1 = MainAccount::findByMainAccountId( 
          '130100'); 
 
          ttsBegin; 
          mainAccount2.data(mainAccount1); 
          mainAccount2.MainAccountId = '130101'; 
          mainAccount2.Name += ' - copy'; 
 
          if (!mainAccount2.validateWrite()) 
         {  
           throw Exception::Error; 
         } 
          mainAccount2.insert(); 
 
          ttsCommit;         
        } 
 
       } 
  1. Navigate to General ledger | Chart of accounts | Accounts | Main accounts again and notice that there are two identical records now, as shown in the following screenshot:

How it works...

In this recipe, we have two variables: mainAccount1 for the original record and mainAccount2 for the new record. First, we find the original record by calling findMainAccountId() in the MainAccount table.

Next, we copy it to the new one. Here, we use the data() table's member method, which copies all the data fields from one variable to another.

After that, we set a new ledger account number, which is a part of a unique table index.

Finally, we call insert() on the table if validateWrite() is successful. In this way, we create a new ledger account record, which is exactly the same as the existing one apart from the account number.

There's more...

As we saw before, the data() method copies all the table fields, including system fields such as the record ID, company account, and created user. Most of the time, it is OK because when the new record is saved, the system fields are overwritten with the new values. However, this function may not work for copying records across the companies. In this case, we can use another function called buf2Buf(). This function is a global function and is located in the Global class, which you can find by navigating to AOT | Classes. The buf2Buf() function is very similar to the table's data() method with one major difference. The buf2Buf() function copies all the data fields excluding the system fields. The code in the function is as follows:

    static void buf2Buf( 
     Common _from, 
     Common _to, 
     TableScope _scope = TableScope::CurrentTableOnly) 
    {  
      DictTable   dictTable = new DictTable(_from.TableId); 
      FieldId     fieldId   = dictTable.fieldNext(0, _scope); 
 
      while (fieldId && ! isSysId(fieldId)) 
     { 
        _to.(fieldId)   = _from.(fieldId); 
        fieldId         = dictTable.fieldNext(fieldId, _scope); 
     } 
    } 

We can clearly see that during the copying process, all the table fields are traversed, but the system fields, such as RecId or dataAreaId, are excluded. The isSysId() helper function is used for this purpose.

In order to use the buf2Buf() function, the code of the MainAccountCopy job can be amended as follows:

    class MainAccountCopyBuf2Buf 
   {         
     /// <summary> 
     /// Runs the class with the specified arguments. 
     /// </summary> 
     /// <param name = "_args">The specified arguments.</param> 
      public static void main(Args _args) 
     { 
       MainAccount mainAccount1; 
       MainAccount mainAccount2; 
 
       mainAccount1 = MainAccount::findByMainAccountId('130100'); 
 
       ttsBegin; 
       buf2Buf(mainAccount1, mainAccount2); 
 
       mainAccount2.MainAccountId = '130102'; 
       mainAccount2.Name += ' - copy'; 
 
       if (!mainAccount2.validateWrite()) 
      { 
        throw Exception::Error; 
      } 
 
       mainAccount2.insert(); 
 
       ttsCommit;         
     } 
 
   }