Designing a journal

Now, it is time to start on the product part of the squash application. In this part, we will no longer reverse engineer in detail. We will learn how to search in the standard functionality and reuse parts in our own software.

For this part, we will look at resources in Microsoft Dynamics NAV. Resources are similar to using as products as items but far less complex making it easier to look and learn.

Our company has 12 courts that we want to register in Microsoft Dynamics NAV. This master data is comparable to resources so we'll go ahead and copy this functionality. Resources are not attached to the contact table like the vendor/squash player tables. We need the number series again so we'll add a new number series to our Squash Setup table.

The Squash Court table should look like this after creation:

Squash court master data

With this chapter some objects are required. A description of how to import these objects can be found in the Appendix, Installation Guide.

Chapter objects

After the import process is completed, make sure that your current database is the default database for the Role Tailored Client and run page 123456701, Squash Setup.

Chapter objects

From this page, select the action Initialize Squash Application. This will execute the C/AL code in the InitSquashApp function of this page, which will prepare the demo data for us to play with. The objects are prepared and tested in a Microsoft Dynamics NAV 2013 R2 W1 database.

When running a squash court, we want to be able to keep track of reservations. Looking at standard Dynamics NAV functionality, it might be a good idea to create a squash player journal. The journal can create entries for reservations that can be invoiced.

A journal needs the object structure. The journal is prepared in the objects delivered with this chapter. Creating a new journal from scratch is a lot of work and can easily lead to making mistakes. It is easier and safer to copy an existing journal structure from the standard application that is similar to the journal we need for our design.

In our example, we have copied the Resource Journals:

Reservations

As explained in Chapter 1, Introduction to Microsoft Dynamics NAV, all journals have the same structure. The template, batch, and register tables are almost always the same whereas the journal line and ledger entry table contain function-specific fields. Let's have a look at all of them one by one.

The Journal Template has several fields, as shown in the following screenshot:

Reservations

Let's discuss these fields in more detail:

The Journal Batch has various fields, as shown in the following screenshot:

Reservations

Let's discuss these fields in more detail:

The Register table has various fields, as shown in the following screenshot:

Reservations

Terms from the Journal Register tab that you need to know would be:

The journal line has a number of mandatory fields that are required for all journals and some fields that are required for their designed functionality.

In our case, the journal should create a reservation which then can be invoiced. This requires some information to be populated in the lines.

For the invoicing part, we need to know the price we need to invoice. It might also be useful to store the cost to see our profit. For the system to figure out the proper G/L Account for the turnover, we also need to define a General Product Posting Group. We will see more of how that works later in Chapter 3, Financial Management.

Invoicing

Let's discuss these fields in more detail:

So now we have a place to enter reservations but we have something to do before we can start doing this. Some fields were determined to be inherited and calculated:

When it comes to the time, we want only to allow specific start and end times. Our squash court can be used in blocks of half an hour. The Quantity field should be calculated based on the entered times and vice versa.

To have the most flexible solution possible, we will create a new table with allowed starting and ending times. This table will have two fields: Reservation Time and Duration.

The Duration field will be a decimal field that we will promote to a SumIndexField. This will enable us to use SIFT to calculate the quantity.

Time calculation

When populated the table will look like this:

Time calculation

The time fields in the squash journal table will now get a table relation with this table. This prevents a user entering values that are not in the table, thus entering only valid starting and ending times. This is all done without any C/AL code and is flexible when times change later.

Time calculation

Now, we need some code that calculates the quantity based on the input:

When a user enters a value in the From Time or To Time fields, the CalcQty function is executed. This checks if both fields have a value and then checks whether To Time is larger than From Time.

Then we place a filter on the Reservation Time table. Now, when a user makes a reservation from 8:00 to 9:00, there are three records in the filter making the result of the Calcsums (total of all records) of duration 1,5. Therefore, we find the previous reservation time and use that.

This example shows how easy it is to use the built-in Microsoft Dynamics NAV functionality such as table relations and Calcsums instead of complex time calculations, which we could have also used.

As discussed in Chapter 1, Introduction to Microsoft Dynamics NAV, there is a special technique to determine prices. Prices are stored in a table with all possible parameters as fields and by filtering down on these fields, the best price is determined. If required, extra logic is need to find the lowest (or highest) price, if more prices are found.

To look, learn, and love this part of the standard application, we have used table Sales Price (7002) and codeunit Sales Price Calc. Mgt. (7000), even though we only need a small part of this functionality. This mechanism of price calculation is used throughout the application and offers a normalized way of calculating sales prices. A similar construction is used for purchase prices with the table Purchase Price (7012) and codeunit Purch. Price Calc. Mgt. (7010).

To calculate the price, we need a codeunit similar to the standard product. This codeunit is called with a squash journal line record and stores all valid prices in a buffer table and then finds the lowest price if there is any overlap:

If there is no price in the filter, it uses the unit price from the squash court, as shown here:

In Microsoft Dynamics NAV, dimensions are defined in master data and posted to the ledger entries to be used in analysis view entries. In Chapter 3, Financial Management, we will discuss how to analyze the data generated by dimensions. In between that journey they move around a lot in different tables as follows:

  • Table 348 | Dimension: This is where the main dimension codes are defined.
  • Table 349 | Dimension Value: This is where each dimension can have an unlimited number of values.
  • Table 350 | Dimension Combination: In this table, we can block certain combinations of dimension codes.
  • Table 351 | Dimension Value Combination: In this table, we can block certain combinations of dimension values. If this table is populated, the value Limited is populated in the dimension combination table for these dimensions.
  • Table 352 | Default Dimension: This table is populated for all master data that has dimensions defined.
  • Table 354 | Default Dimension Priority: When more than one master data record in one transaction have the same dimensions, it is possible here to set priorities.
  • Table 480 | Dimension Set Entry: This table contains a matrix of all used dimension combinations.
  • Codeunit 408 | Dimension Management: This codeunit is the single point in the application where all dimension movement is done.

In our application, dimensions are moved from the squash player, squash court, and customer table via the squash journal line to the squash ledger entries. When we create an invoice, we move the dimensions from the ledger entries to the sales line table.

When we use the master data records in the journal table, the dimensions are copied from the default dimension table to the dimension set entry table. This is done using the folowing piece of code that is called from OnValidate of each master data reference field:

To decide which dimensions to inherit, we should first analyze which master data is used in our Journal that is using default dimensions.

In our case, Table[1] is Squash Player, Table[2] is Squash Court, and Table[3] is Customer. The dimension management codeunit makes sure everything is copied. We can use standard Microsoft Dynamics NAV functions.