Microsoft Dynamics NAV 2009: Apply reverse engineering to customize our application

With this book you’ll quickly learn to develop complete Dynamics NAV applications and gain the versatility to design for different enterprise needs and industry sectors. With a user-friendly, fully focused approach it’s an indispensable tutorial.

(Further on Microsoft Dynamics NAV:here.)

Fit-gap analysis

When we do a fit-gap analysis we look at the company's processes and define what we can and cannot do with the standard package. When a business process can be handled with the standard software we call this a Fit. When it cannot be done it's a Gap, we can fill a gap by developing a solution or purchasing an add-on.

But even when something could be done with standard software features, it does not necessarily mean that doing this is wise. The standard application should be used for what it was designed for. Using standard features for something else might work in the current version but if it changes in a new version it might no longer fit. For this reason it is better to design something new instead of wrongly using standard features.

Designing a Squash Court application

The basic process of a squash court company is renting the courts to squash players; both members and non-members. There is a reservation and invoicing process handling different rates for members and non-members.

Although this could be implemented using items to represent squash courts and customers to represent players this would be a typical example of using standard features wrongly. Instead of doing this we will look at how items and customers are designed and use this to create a new Squash Court application.

Look, learn, and love

To determine the design for this application we will first look at the parts of the standard application (we could have used) to learn how they work. We will use this knowledge in our own design.

In Microsoft Dynamics NAV, customer and vendor master data are maintained using Relationship Management (RM). For our solution we will create a new master data for squash players being the business part of application. This will also be integrated with RM.

To design the Squash Court we will look at the design of items in the standard package. The Squash Court will be the product part of our application having a journal to create reservation entries, which we can invoice.

For this invoicing process we will use and integrate with the Sales part of Microsoft Dynamics NAV.

Drawing the table and posting schema

After we have decided what the design of our application will be, we can draw the tables and post the routines. This will clarify the design for others and guide us through the development process.

The objects in Relationship Management and Sales are standard objects that we will possibly need to modify. The objects for the Squash Application are new objects but based on similar objects in the standard application.

The objects in Relationship Management and Sales are standard objects that we will possibly need to modify. The objects for the Squash Application are new objects but based on similar objects in the standard application.

The Project approach

In order to keep track of our project we'll cut the changes into smaller tasks. The first task will be to do the changes in Relationship Management to be able to create a squash player from a contact. The second task is to create squash courts. The reservation and invoice processes are tasks three and four.

Interfacing with the standard application

In our schema we can see that we have two processes where we need to touch the standard Microsoft Dynamics NAV processes, which are Relationship Management and Sales.

Getting started

In the first part of the design process we will look at how to reverse engineer the standard application in order to learn and reuse the knowledge in our own solution.

Creating squash players

For our squash players administration we will use the data from the Contact table. In the standard product it is possible to create a customer or vendor with the contact data. We require the same functionality to create squash players so let's have a look at how this is done by Microsoft.

Open the contact card and try to find this function (as shown in the following screenshot):

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

We want a function like this for our squash players. So let's get in and see what it does. For this we need to design the page and look at the actions. The page number in this case is 5050 which we can find by clicking on About This Page in the upright corner of the page as shown in the following screenshot:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

This option can be useful for finding information about the fields that are not on the page, the filters or the source table:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

To open the page we need to open the Object Designer (Shift F12) in the Classic client as shown in the following screenshot:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Here in the Object Designer we can find page 5050, Contact Card, as shown:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

We are looking for the Actions on this page. They are kind of difficult to find if you are unfamiliar with the Page Designer. To open the Actions, the cursor should be on the blank line below the last populated line. Then press the right mouse button and Actions or select Actions from the View drop down menu:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Now we are in the Action Designer and we can search for the Create as part.

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

To see what it does we need to go into the C/AL code by pressing F9 or by selecting C/AL Code from the View drop down menu as shown in the following screenshot:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

CreateVendor versus CreateCustomer

In Microsoft Dynamics NAV there is a small difference between creating a customer and a vendor from a contact. When creating a customer the system will ask us to select a customer template. The vendor option does not have this. Because of this simplicity we will look at and learn from the Vendor function in this article.

The customer and vendor table are almost identical in structure and fields are numbered similar in both tables. This is called transaction mirroring between sales and purchasin. We will mirror our new table in a similar way to the other Microsoft Dynamics NAV tables.

The C/AL code in the Action tells us that while pushing the menu option, the function CreateVendor in the contact table is started. To copy this feature we need to create a new function CreateSquashPlayer. Let's keep this in mind while we dive further into this code.

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Open the Contact table (no. 5050), and search the function CreateVendor. You can find functions in a table by going into the C/AL code (F9) from anywhere in the table designer, and use the Find (Ctrl+F) function as shown in the following screenshot:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

(Further on Microsoft Dynamics NAV:here.)

Reverse engineering

We need to reverse engineer this code in order to see what we need to create for our CreateSquashPlayer function. We will look at each part of the C/AL code in order to decide whether we need it or not.

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

What does this piece of code do?

TESTFIELD("Company No.");

This tests the current record for a valid Company No. If this fails we cannot continue and the end user get's a runtime error.

RMSetup.GET;
RMSetup.TESTFIELD("Bus. Rel. Code for Vendors");

This reads the marketing setup table from the system and tests whether the Bus.Rel. Code for Vendors is valid. We need a new code for squash players here, which will be added as a new field to the setup table.

CLEAR(Vend);
Vend.SetInsertFromContact(TRUE);
Vend.INSERT(TRUE);
Vend.SetInsertFromContact(FALSE);

Here, the vendor table is cleared and a function is called within that table, then a new record is inserted in the database while activating the necessary business logic. Then the same function is called again with another parameter. Since the vendor table is what we are copying we will write down that we might need a similar function as SetInsertFromContact.

IF Type = Type::Company THEN
ContComp := Rec
ELSE
ContComp.GET("Company No.");

This code checks whether the current contact is a company. If so it populates the variable ContComp with this record. If not it populates ContComp with the company our current contact is related to.

ContBusRel."Contact No." := ContComp."No.";
ContBusRel."Business Relation Code" := RMSetup."Bus. Rel. Code for
Vendors";
ContBusRel."Link to Table" := ContBusRel."Link to Table"::Vendor;
ContBusRel."No." := Vend."No.";
ContBusRel.INSERT(TRUE);

The ContBusRel refers to the table, Contact Business Relation (5054), and is a linking table in the Microsoft Dynamics NAV data model. Technically a contact can be connected to multiple customers and vendors although this does not make sense. This table is populated here. Let's write down that we need to look into this table and see if it needs changes.

UpdateCustVendBank.UpdateVendor(ContComp,ContBusRel);

UpdateCustVendBank is an external code unit that is used with the function, UpdateVendor, we might need a copy of this function for our Squash players.

MESSAGE(Text009,Vend.TABLECAPTION,Vend."No.");

This throws a message box for the end-user stating that the record was created with a new number.

Now we have a number of things on our to-do list:

  1. Create a master data table which looks like the vendor table.
  2. We need to copy the CreateVendor function.
  3. Look at the contact business relation table and the UpdateCustVendBank (5055) code unit.

Let's look at the latter to learn something important before we start with the first.

UpdateVendor()
WITH Vend DO BEGIN
GET(ContBusRel."No.");
xRecRef.GETTABLE(Vend);
NoSerie := "No. Series";
PurchaserCode := Vend."Purchaser Code";
TRANSFERFIELDS(Cont);
"No." := ContBusRel."No.";
"No. Series" := NoSerie;
Vend."Purchaser Code" := PurchaserCode;
MODIFY;
RecRef.GETTABLE(Vend);
ChangeLogMgt.LogModification(RecRef,xRecRef);
END;

This code synchronizes the contact table with the vendor table. It does that by using the TRANSFERFIELDS function. This function transfers all fields with the same number from one table to another. This means that we cannot be creative with our field numbering. For example, in the contact table the Name field has number 2. If we were to use a different number for the Name field then TRANSFERFIELDS would not copy the information.

Using this information our table should look like this:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Notice that we use field 19 for our Squash Player specific field. This is because field 19 was used for Budgeted Amount in the vendor table. We can therefore safely assume that Microsoft will not use field 19 in the contact table in the future.

An alternative approach for this, if we want to be even safer, is to add the fields that are specific to our solution as fields in our add-on number series. In our case that would be 123.456.700.

You can copy and paste fields from one table to another table. Note that table relations and C/AL code in the OnValidate and OnLookup trigger is copied as well. If the table we want to create is similar to an existing table we could also use the Save As option from the File drop-down menu.

The next step is to add some business logic to the table. We want this table to use number series functionality just like the vendor table. This requires some standard steps:

  1. Create the Setup table: A number series is defined in a setup table. As the Squash Court module will be quite sophisticated, we'll create our own.

    Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

    A setup table always has a single Primary Key field (as shown in the previous screenshot) and the necessary setup fields. This table is designed to only have one single record.

  2. Create a link to the number series: Our Squash Player table is now required to have a link to the number series. We can copy this field from the vendor table and can make a table relation to the No. Series table (as shown in the following screenshot):

    Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

  3. Add the C/AL Business Logic: Now we can add the business logic to our table, but first we need to define the variables that are required. These are our new SquashSetup table and the number series management codeunit.

    Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

    We can define the variables in the specially created C/AL Globals menu (as shown in the screenshot):

    Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Number Series require three pieces of code. This code makes sure that the business logic of the Number Series functionality is always followed:

  1. The OnInsert Trigger: This code goes into the OnInsert trigger. It populates the No. field with the next value of the Number Series.

    OnInsert()
    IF "No." = '' THEN BEGIN
    SquashSetup.GET;
    SquashSetup.TESTFIELD("Squash Player Nos.");
    NoSeriesMgt.InitSeries(SquashSetup."Squash Player Nos.",
    xRec."No. Series",0D,"No.","No. Series");
    END;

  2. The OnValidate Trigger of the No. field: The OnValidate code of the No. field tests when a user manually enters a value if that is allowed.

    No. - OnValidate()
    IF "No." <> xRec."No." THEN BEGIN
    SquashSetup.GET;
    NoSeriesMgt.TestManual(SquashSetup."Squash Player Nos.");
    "No. Series" := '';
    END;

  3. Create a new AssistEdit function: Lastly, we create a new function. This is always called AssistEdit. This is for readability and others reading your code afterwards. The code is used in the page or form and allows users to switch between linked number series.

    AssistEdit() : Boolean
    SquashSetup.GET;
    SquashSetup.TESTFIELD("Squash Player Nos.");
    IF NoSeriesMgt.SelectSeries(SquashSetup."Squash Player Nos.",
    xRec."No. Series","No. Series")
    THEN BEGIN
    NoSeriesMgt.SetSeries("No.");
    EXIT(TRUE);
    END;

When the number series are in place we can make the necessary changes in the Contact Business Relation table.

In this table we need to add the possibility to link squash players to contacts. This is done in the properties window of the Table Designer that can be accessed by pressing Shift +F4 or by using the Properties option from the View drop-down menu (as shown in the following screenshot):

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

First we add the Squash player option to the Link to Table field (as shown in the following screenshot):

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

Options are converted to SQL Integer data types. Make sure to add some blank options so when Microsoft releases other functionality we are not impacted. Changing the integer value of an existing option field requires a lot of work.

Then we create a table relation with our new table (as shown in the following screenshot):

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

The next step is to expand the Codeunit CustVendBank-Update with a new function UpdateSquashPlayer (as shown in the following screenshot). This is a copy of the function UpdateVendor we discussed earlier. We can add functions in the Globals menu.

There are two ways to copy a function. We can create a new function manually and copy the C/AL code and variables, or we can select a function from the list and use copy and paste and then rename the function:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

When you add the—line to the function others can see that it is not a Microsoft function. You can also include the project name like—Squash.

This code also requires a new global variable, SquashPlayer:

UpdateSquashPlayer()
WITH SquashPlayer DO BEGIN
GET(ContBusRel."No.");
xRecRef.GETTABLE(SquashPlayer);
NoSerie := "No. Series";
TRANSFERFIELDS(Cont);
"No." := ContBusRel."No.";
"No. Series" := NoSerie;
MODIFY;
RecRef.GETTABLE(SquashPlayer);
ChangeLogMgt.LogModification(RecRef,xRecRef);
END;

The final piece of preparation work is to add the Bus. Rel. Code for Squash Players field to the Marketing Setup table as shown in the following screenshot:

Microsoft Dynamics NAV 2009: Apply reverse engineering to  customize our application

We use the same numbering in our fields as in our objects. This makes it easier in the future to see what belongs to what if more functionality is added.

With all this preparation work we can now finally go ahead and make our function in the contact table (5050) that we can call from the user interface.

CreateSquashPlayer()
TESTFIELD(Type, Type::Person);

RMSetup.GET;
RMSetup.TESTFIELD("Bus. Rel. Code for Squash Pl.");

CLEAR(SquashPlayer);
SquashPlayer.INSERT(TRUE);

ContBusRel."Contact No." := Cont."No.";
ContBusRel."Business Relation Code" :=
RMSetup."Bus. Rel. Code for Squash Pl.";
ContBusRel."Link to Table" :=
ContBusRel."Link to Table"::"Squash Player";
ContBusRel."No." := SquashPlayer."No.";
ContBusRel.INSERT(TRUE);

UpdateCustVendBank.UpdateSquashPlayer(Cont,ContBusRel);

MESSAGE(Text009,SquashPlayer.TABLECAPTION,SquashPlayer."No.");

Please note that we do not need the SetInsertFromContact function. This function enables users to create a new Vendor first and Create a Contact using the Vendor information. We do not want to support this method in our application.

Now we can add the function to the page and test our functionality:

Summary

In this article we have learned:

  • how to to reverse engineer the standard application to look and learn how it works
  • how to reuse the structures in our own solutions.

Further resources on this subject:


Books to Consider

comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free