Vous êtes sur la page 1sur 320

Draft Version

Navision Attain Solution Development

Draft Version

Navision Attain Solution Development

NOTICE This material is for informational purposes only. Navision a/s disclaims all warranties and conditions with regard to use of the material for other purposes. Navision a/s shall not, at any time, be liable for any special, direct, indirect or consequential damages, whether in an action of contract, negligence or other action arising out of or in connection with the use or performance of the material. This material is subject to change without notice. According to Danish copyright legislation it is against the law to reproduce any part of this material in any form or by any means without the permission of Navision a/s. The software described is supplied under license and must be used and copied in accordance with the enclosed license terms and conditions. COPYRIGHT NOTICE Copyright 2001 Navision a/s, Frydenlunds All 6, DK-2950 Vedbk, Denmark or Copyright 2001 Navision Development a/s, Bregnerdvej 133, 3460 Birkerd, Denmark. All rights reserved. TRADEMARKS The trademarks referenced herein and marked with either
TM

or are either

trademarks or registered trademarks of Navision a/s or Navision Development a/s. However, the trademarks Microsoft, Windows, Windows NT, SQL Server and BackOffice are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Any rights not expressly granted herein are reserved. The trademarks of Navision a/s and Navision Development a/s are listed on this Web site: http://trademarks.navision.com The MetaPlus font was used. Published by Navision a/s. Published in Denmark 2001.

Table of Contents

Navision Attain Solution Development

Table of Contents

Chapter 1 1.1

Complex Data Types What is a Complex Data Type?

1.2 Using the Objects You Know 1.3 What About the Table Data Type? 1.4 Member Functions of Record Data Types 1.5 Using Versions, Transactions and Optimistic Concurrency

Chapter 2

Coding in Tables, Reports and Dataports

2.1 What is a Trigger? 2.2 Table and Field Event Triggers 2.3 Report Event Triggers 2.4 Special Report Functions and Where They Belong 2.5 Processing Only Reports 2.6 Dataports Event Triggers

Chapter 3

Object Analysis

3.1 Exporting Objects as Text 3.2 Editing an Object Using an External Text Editor 3.3 Changing the Text File

3.4 Object Analysis with Developers Toolkit

Chapter 4

Development Methodology

4.1 Implementation Methodology 4.2 Version Control 4.3 Development Documentation

Table of Contents

Chapter 5

Posting Routines

5.1 What is the Difference between a Journal and

a Ledger?
5.2 Standard Journal to Ledger Posting Routines 5.3 The Main Three Codeunits 5.4 The Theory behind Document Posting 5.5 The Codeunits Used in Document Posting

Chapter 6

Data Conversion

6.1 Transaction Imports 6.2 Importing Documents 6.3 File Handling in Navision Attain

Chapter 7

Coding in forms

7.1 Form Triggers 7.2 Triggers for Rec 7.3 Control Trigger 7.4 Special Form and Control Functions

Chapter 8

Low Impact Programming

8.1 Low Impact on the Application 8.2 Low Impact on the Server 8.3 Low Impact on the Network 8.4 Low Impact on the Database

ii

Table of Contents

Chapter 9

The Upgrade Process

9.1 Why Upgrade 9.2 Definitions 9.3 Types of Upgrades 9.4 Planning for an Upgrade 9.5 Upgrading the Executables 9.6 Upgrading the Objects. 9.7 Tools for Upgrading the Objects 9.8 What If? 9.9 Upgrading the Data

Lab 1

Complex Data Types 1.1 Running Objects

1.2 Using Dialogs 1.3 Getting Started With Record Variables 1.4 Using Streams

Lab 2

Coding in Tables, Reports and Dataports 2.1 Coding in Table and Field Event Triggers 2.2 Coding in Report Event Triggers 2.3 Coding in Dataport Event Triggers

Lab 3

Object Analysis 3.1 Exporting and Changing as Text 3.2 Renumbering Objects 3.3 Analysis with impuls Workbench

Lab 4

Development Methodology 4.1 Internal Documentation 4.2 External Documentation 4.3 Setting the Version List 4.4 Completing Design Specifications

iii

Table of Contents

Lab 5

Posting Routines 5.1 Getting Ready 5.2 Creating Check Line 5.3 Creating Post Line 5.4 Creating Post Batch 5.5 Creating a Starter Routine Post 5.6 Changing a Document Posting Routine

Lab 6

Data Conversion 6.1 Looking at the Import File 6.2 Debugging the Journal 6.3 Building the Transaction Dataport 6.4 Testing the Transaction Dataport 6.5 Changing the Dataport to Post Directly 6.6 Another Exercise

Lab 7

coding in Forms 7.1 Creating a Menu 7.2 Integration with the Main Menu 7.3 Creating a Statistics Form 7.4 Using a Matrix Box 7.5 Using the Hyperlink triggers

Lab 8

Property Management 8.1 Introduction 8.2 Concept Document 8.3 Design Specifications

Lab 9

The Upgrade Process 9.1 Upgrading a Customized Database

iv

Chapter 1 Complex Data Types

This chapter introduces the complex data types found in C/SIDE. It helps the student focus on the most used complex data types with special emphasis on the record data type. This chapter will cover the following sections: 1.1 What is a Complex Data Type? 1.2 Using the Objects You Know 1.3 What About the Table Data Type? 1.4 Member Functions of Record Data Types 1.5 Using Versions, Transactions and Optimistic Concurrency Chapter Review

1-2

Navision Attain Solution Development

1.1 What is a Complex Data Type?


Complex data types are those that have more than just a value and operators. Simple data types like integers have a value. You can add or subtract integers to get new values and so on. Complex data types, however, have properties or methods along with a value (or values). For instance, a form data type has a value (the form object), but it also has methods like the RUN method that displays the form to the user. It also has properties like LOOKUPMODE. Remember that Arrays of any type are also called complex, but Arrays are complex variables not complex data types. A Complex Variable is a variable that has a complex data type or is an array (has one or more dimensions defined).

Complex Data Types


Automation BLOB Codeunit Dataport Dialog File Form InStream Allows access to an external Applications Object interface. Can only be used as a Field data type. Allows access to a Codeunit object. Allows access to a Dataport object. Used to display a status window to the user (includes a Cancel button) Allows access to external files. Allows access to a Form object. Allows streaming of data out of Files and Blobs. This datatype is also useful when working with Automation and OCX datatypes. OCX Allows access to an external OCX control (only non-visual OCX controls are supported. OutStream Allows streaming of data into Files and Blobs. This datatype is also useful when working with Automation and OCX datatypes. Record Report Variant Allows access to Table Data. Allows access to a Report object. Can hold any C/AL data type and can be assigned to and from any C/AL data type. You can use the variant data type to pass Automation variants from one external component (Automation or OCX) to another.

Complex Data Types

1-3

Note You will not be learning about OCX, Automation, BLOB or File in this section. These data types have already been covered or will be covered by other sections.

1-4

Navision Attain Solution Development

1.2 Using the Objects You Know


In this section, you will learn how to use the objects you already understand (forms, reports, dataports and codeunits) within C/AL. All of these data types have one method in common, the RUN method. You will use this method and several others in this section.

Accessing Codeunits As reviewed in the basic C/AL section, a codeunit in Navision can be used to hold functions that are common to many other objects. An example would be the NumberSeriesManagement codeunit. It holds functions that allow you to manipulate Number Series such as getting the next number in a particular series. By putting common code into Codeunits, the Developer can take full advantage of code re-use. You can access the code in a codeunit from other objects in several ways:

Using a Codeunit Variable By creating a codeunit variable, you have an instance of the codeunit object. As long as that instance exists, it maintains the values of its global variables. This is one reason why you would choose this method. The other reason is more obvious. This is the only way of accessing the functions within a codeunit. To use a codeunit variable: 1 2 3 Create a variable of type codeunit In the subtype field, put the name or ID of the codeunit you want to access. Within C/AL, you can call the RUN method of the codeunit or a function within the codeunit. You can pass a record variable into the RUN method if the OnRun trigger will accept one.

Examples: CodeunitVariable.RUN; //No record variable CodeunitVariable.RUN(Rec); //With record variable X := CodeunitVariable.AddTen(9001); //Calling a function

Complex Data Types

1-5

Using the CODEUNIT.RUN Function By using the CODEUNIT.RUN function to create and run a codeunit, you dynamically create an instance of a codeunit based on the ID. Since the instance is created, ran and destroyed in this one statement, there is no codeunit variable to worry about, and the destruction of the codeunit clears all of its variables as well. The other benefit to using this method is that you can create any codeunit based on the ID. So, this is a dynamic creation. The biggest drawback to this function is that you can only run the codeunit. You can still pass in a record variable, but you cannot call a function within the codeunit. To run a codeunit using CODEUNIT.RUN: Call the run method of the codeunit using the global codeunit object. You must pass in the ID of the codeunit that you wish to run. You can pass a record variable if the OnRun trigger of that codeunit will accept one.

Example: CODEUNIT.RUN(393); //No record variable CODEUNIT.RUN(393, Rec); //With record variable Accessing Forms Forms can be run in much the same way as codeunits, with a form variable or using the FORM.RUN function. However, there is another way to run forms. You can run them modally using the RUNMODAL method instead of RUN.

Examples (running a form non-modally) CustomerCardVariable.RUN; FORM.RUN(FORM::Customer Card, CustRec);

Examples (running a form modally) By running a form modally, you can check what button the user pushed to close the form. In this example, the customer list form is run modally and if the user pushed the OK button, a variable is changed. IF FORM.RUNMODAL(22,CustRec) = Action::LookupOK THEN CustNo := CustRec.No.;

1-6

Navision Attain Solution Development

Accessing Reports and Dataports As with forms, reports and dataports can be run with a variable, without a variable, modally or non-modally.

Examples ReportVariable.RUN; REPORT.RUN(ReportID); ReportVariable.RUNMODAL; DataportVariable.RUN; DATAPORT.RUN(DataportID); DataportVariable.RUNMODAL; For more information about running a report or dataport, see the online help pages for the above functions.

Activity In this activity, you will create a codeunit that runs two reports and then calls that codeunit from a button on a form. 1 2 3 Create a codeunit, with ID 99100 and Name ReportRunTest. Create a function in the codeunit called Go. In that function, write code that will run report 5201- Employee List (run this report using a variable) and 5200- Employee Labels (run this report without using a variable). Go to the Employee form (Form 5200) and add a menu item to the Customer menu button that will call the function in the codeunit you just wrote. Test your new functionality.

Complex Data Types

1-7

1.3 What About the Table Data Type?


You may have noticed that there was one very important object missing from the discussion in the last section Tables. You may be wondering if you can run tables from code, or better yet insert records. Well, there is no Table data type that you can create in Navision. But you can access tables through record data types. These variables are called record variables. Record variables are the guards that protect the data. They are used to access data, change and manipulate the data. There are a few concepts that you must keep in mind when working with record variables: The record variable is a place in the memory for ONE record from the associated table. The record variable is also conscious of the entire set of records contained in the table. The record variable is NOT the record in the table, or the table itself. No table data can be accessed except through a record variable.

The other objects throughout C/SIDE use record variables to access or change data in a table. Here are some examples: Forms use a Record Variable called Rec (table objects themselves also use a record variable called Rec). Reports and Dataports use DataItems that are actually record variables. In code, one can create Global or Local Variables that are of type Record.

Record variables have fields just like the table that they access. For example, a record variable with a subtype of Customer would have fields like No., Name, Address, City and so on. But changing the fields of a record variable does not change the record in the database. You will learn how to change the database in the next section.

1-8

Navision Attain Solution Development

1.4 Member Functions of Record Data Types


You cannot run a record variable, but there are many other member functions that you must master in order to really use record variables successfully.

Retrieving a Record In order to retrieve a record or navigate to the next record in a record set, you must use one of the following method functions. These functions allow the developer to search for specific records depending on the criteria entered or move forward or backwards in the record set.

GET The most basic way to retrieve a record in C/SIDE is with the GET method. This method uses the primary key values to find the matching record in the database. Once the record is found, it sets the record variables fields to the values of the fields in the database. Afterward, you have a copy of the database record in the record variable. The GET method ignores the record set and goes directly to the table to retrieve the record. If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function. Examples: Customer.GET('50000'); //No. is the primary key field ItemUnitOfMeasure.GET('70000', 'PCS'); //Compound Primary key Customer.GET(CustNo); //Using a variable Customer.GET(Rec.No.); //Using a field from another // Record Variable //Avoiding the error if it fails IF Customer.GET(CustNo) THEN ... FIND The FIND method is another important way of retrieving records from the database. It is used to go to a specific record in a record set. Usually this function is just used to go to the first or the last record within a record set, but you can use it for searching as well. An important difference between GET and FIND is that FIND respects (and is limited by) the current setting of filters. Additionally, FIND can be instructed to look for records where the key value is equal to, larger than or smaller than the

Complex Data Types

1-9

search string. The parameter for find is a string that can be any one of the following: +, -, =, <, or >. Find(+) goes to the bottom of the table and sets the record variable to the last record. Find(-) goes to the top of the table and sets the record variable to the first record. If you use =, <, or >, FIND will take into account values currently stored in the record variable fields which are included in the current key. If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function.

Examples SalesOrderLine.SETRANGE("No.","No."); //Filter the record set SalesOrderLine.FIND('-'); //Find the first Customer.SETCURRENTKEY("Search Name"); //Change the order Customer.FIND('+'); //Find the last Customer.SETCURRENTKEY("Search Name"); //Change the order Customer."Search Name" := 'J'; //Set field Customer.FIND('=><'); //Find the nearest //Avoiding the error if it fails IF Customer.FIND('-') THEN ...

NEXT Once you have retrieved a record from the database, you may want to retrieve the very next record or a previous record. The NEXT method allows you to do that. The steps parameter allows you to specify direction and number of records to jump over. A negative number does a previous. A positive number does a next. The default value is 1. If you enter a 3 for steps, the function will jump over the next two records and retrieve the third one. The NEXT method returns a zero if it could not retrieve the specified record. If zero is returned, the record variable is not changed at all. Examples Customer.FIND('-'); //go to First record (10000) Customer.NEXT; //go to Next record (20000) Customer.NEXT(-1); //go to Previous record (10000)

1-10

Navision Attain Solution Development

Customer.NEXT(-1); Customer.NEXT(3); Customer.FIND('+'); Customer.NEXT;

//returns zero (stays on 10000) //go to the third record (40000) //go to last record //returns zero

//Looping thru a table IF Customer.FIND('-') THEN REPEAT //work with customer record UNTIL Customer.NEXT = 0; Modifying the Database Record To change the database record that a record variable represents, you must use one of the following functions: INSERT, MODIFY, RENAME, DELETE, MODIFYALL, or DELETEALL. All of these functions look at the values in the primary key fields of the record variable to determine which record to change.

INSERT Use this function to insert a record into a table. It takes the values of the fields in the record variable and inserts those into the table. If you want to run the OnInsert trigger of the table during the insert, you must pass TRUE into the function. If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function. This is usually not done. Example: //Inserting a record into a table Customer.INIT; Customer."No." := '4711'; Customer.Name := 'John Doe'; Customer.INSERT(True); //Calling the OnInsert Trigger //Avoiding the error if it fails IF Customer.INSERT THEN ...

MODIFY The MODIFY method allows you to update the database record with the values in the record variable that have changed. If you want to run the OnModify trigger of the table during the modification, you must pass TRUE into the function.

Complex Data Types

1-11

If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function. This is usually not done. Example: Customer.GET('4711'); Customer.Name := 'Richard Roe'; Customer.MODIFY(True); //Calling the OnModify trigger //Avoiding the error if it fails IF Customer.MODIFY THEN ...

DELETE The DELETE method allows you to erase or remove the database record identified by the primary key values in the record variable. If you want to run the OnDelete trigger of the table during the deletion, you must pass TRUE into the function. If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function. This is usually not done. After the successful deletion of the record in the database, the record variable is not changed. It retains the same values that it had before the deletion. Example: Customer."No." := '4711'; Customer.DELETE(True); //Calling the OnDelete trigger Customer.GET(50000); Customer.DELETE; //No trigger called

RENAME The RENAME method can be used to change the primary key fields of a record in the database. Like the GET method, you must pass the new primary key values as parameters to this function. It uses the values in the primary key fields of the record variable to find the record in the database and then uses the new values to change the record. This function works the same as the user changing the primary key fields on a form the change is propagated to all related tables. The OnRename trigger is always called. If unsuccessful, an error occurs. You can trap the error by looking at the return value of the function. This is usually not done.

1-12

Navision Attain Solution Development

Example: Customer."No." := '4711'; Customer.RENAME(15000); trigger //Calls the OnRename

ItemUnitOfMeasure.GET(70000,PCS); ItemUnitOfMeasure.RENAME(70000,PIECES);

Activity In this activity, you will sort the customer table, find a record and modify the record. First, you will perform the task as the user might do it. Then, you will write code to accomplish the same task.

Before You Get Started 1 Create a key in the customer table that contains the Credit Limit (LCY) field.

By Hand 2 3 Run the customer table from the object designer. Using the sort button on the toolbar, change the form to sort by the "Credit Limit (LCY) key that you just created. Using the navigation buttons on the toolbar, go to the first record and then the last record. Add 100.00 dollars to the Credit Limit of the last record.

In Code 6 7 8 Create a codeunit, with ID 99101 and Name ModfiyCustomer. Create a function in the codeunit called AddToCreditLimit. Create a global variable, call it Customer. The type is record and the subtype is 18.

Complex Data Types

1-13

In the AddToCreditLimit function, you can type in the following code:

Customer.SETCURRENTKEY("Credit Limit (LCY)"); Customer.FIND('+'); Customer."Credit Limit (LCY)" := Customer."Credit Limit (LCY)" + 100.00; Customer.MODIFY; Defining a Record Set A Record Variable represents a record set from a single table. You can easily have two or more Record Variables pointing to the same table looking at a completely different set of records. But, how do you create a record set? In this subsection you will learn about the functions that allow you to change the set of records that the record variable represents. A set of records can be referred to by the term Record Set. A Record Set is defined by the Key and Filters that the record variable has been assigned. This is sometimes called a View. To assign a new key or filter to a Record Variable, use the method functions SETCURRENTKEY, SETRANGE or SETFILTER. You must understand all of these functions to effectively use record variables.

SETCURRENTKEY The SETCURRENTKEY method assigns a new key to a record variable. All record variables use the primary key by default. If you would like to sort the records in a different way, you must use this method function. The new key becomes the current key and is used by FIND, NEXT and other functions until another key is selected or until the key is reset to the primary key. What you pass into this function is a list of fields. The function then searches the tables keys to find a matching key. It starts at the top of the list of active keys and tries each one until it finds a key that works. This may or may not be the best key. It is the first key in the list that works. A run-time error occurs if the function cannot find a Key that contains all the fields specified in the order specified. You can trap this error by looking at the return value of the function.

1-14

Navision Attain Solution Development

Examples Customer.SETCURRENTKEY("Search Name"); //Sorts by Search Name Customer.SETCURRENTKEY("No."); //resets to the primary key Customer.SETCURRENTKEY(Address,City); //Fails with an error //Trapping the error IF Customer.SETCURRENTKEY(Address,City) THEN ...

SETRANGE The SETRANGE method provides a quick way to set a simple filter on a field. If you call this function with a field that already has a filter, the system removes that filter before it sets the new one. A range in C/SIDE is of the form "FromValue ToValue". This is the only type of filter that SETRANGE can perform. Once a filter is applied to the record variable, the record set is changed so that it only includes those records that meet the filter criteria. Using the FIND or NEXT methods on a filtered record set will only retrieve records in that record set. The GET method however ignores all filters and gets the record from the database if it can. Examples Customer.SETRANGE("No.",'10000','90000'); //Includes first 5 Customer.SETRANGE("No.",'30000'); //Includes just 30000 Customer.SETRANGE("No."); //removes all filters on No. Customer.SETRANGE("No.",'111'); //Includes NO records //Displaying a filtered record set Customer.SETCURRENTKEY("Search Name"); //Always set a key Customer.SETRANGE("Search Name",'D','K'); //set filter FORM.RUN(FORM::"Customer List", Customer); //call form pass rec

SETFILTER The SETFILTER method provides a way to set a complex filter on a field. If you call this function with a field that already has a filter, the system removes that filter before it sets the new one. You can construct filters using these operators: (), .., &, |, <, <=, >, <>, *. You can also use replaceable parameters (%1, %2 and so on) just like the MESSAGE function.

Complex Data Types

1-15

Examples //Filter down to the first three customers Customer.SETFILTER("No.", '10000|20000|30000'); //Filter down customers with credit limits over 17,500 Customer.SETFILTER("Credit Limit (LCY)", '>17500'); //Filter down to all customers after 10000 but not 20000 Customer.SETFILTER("No.", '>10000 & <> 20000'); //Filter down to customers with the First letter J or K Customer.SETFILTER("Name", 'J*|K*');

RESET The RESET method removes all Filters and resets the key to the primary key. Examples Customer.SETCURRENTKEY("Search Name"); Customer.SETRANGE("Search Name", 'J','K'); Customer.RESET; //Puts the record variable back to original Other Methods INIT Use the INIT method to initialize a record variable. The function does not initialize primary key fields.

CALCFIELDS Use this function to force the calculation of FlowFields or BLOBs in a record variable. By default, the record variable does not calculate these types of fields. You must specify the FlowFields or BLOBS that you want to calculate. Example GLAccount.SETRANGE("Date Filter",0D,WORKDATE); GLAccount.CALCFIELDS(Balance,"Balance at Date");

COPY Use this function to copy a record variable to another record variable. All fields, filters, marks and keys are included in the copy.

1-16

Navision Attain Solution Development

Example Customer.COPY(CustRec);

COUNT Use this function to count the number of records in the record set, represented by the record variable. This will take into account any Filters that are set and use the current key (which can increase or decrease the speed depending on the filters set).

Example X := Customer.COUNT;

LOCKTABLE Use this function to lock the table that the record variable is bound to. This can protect it from other users attempts to write to the same table. If the wait parameter is True, the function will wait until the table is unlocked to proceed. Otherwise, if the table is locked, you will receive a run-time error. The default value for the wait parameter is True. Note Do not use CONFIRM in connection with LOCKTABLE. If the VersionCheck parameter is True, the system will assure that all modifications are done on the same version of the database as when the record was read. If that record has been changed, a run-time error occurs. The default value for this parameter is False. Whenever a write operation is performed on a table which has not been explicitly locked, an implicit LOCKTABLE with both parameters set to their defaults, is automatically performed. Examples Customer.LOCKTABLE; Customer.LOCKTABLE(FALSE); Customer.LOCKTABLE(True,True); version //Using the defaults //Dont wait if locked //Wait but use same

Complex Data Types

1-17

VALIDATE Use this function to call the OnValidate trigger for the field you specify. If NewValue is passed in, the function will first assign the Field with NewValue. The VALIDATE method first checks the TableRelation property and then executes the OnValidate trigger of the field. Examples Customer.VALIDATE("Salesperson Code"); //checks tablerelation // no code in trigger Customer.VALIDATE("No."); //no tablerelation; executes code.

Activity In this activity, you will loop through the customer table and set the credit limit for all customers. You will filter first to avoid changing customers that already have a credit limit. Can you find problems with this outlined logic?
1 2 3

Open the codeunit ModfiyCustomer (99101). Create a function in the codeunit called SetAllCreditLimits. In the function, set the current key to the "Credit Limit (LCY)" field. Use the Customer record variable that already exists. Set a filter so that the record set includes only records that have a zero credit limit. Loop through the records using a repeat loop. Dont forget the Find(-) at the beginning. Inside the loop add code to modify credit limit to be the balance * 10. If the balance is zero, set the credit limit to 10,000. Dont forget to calculate the Balance FlowField. Test you function by putting code in the OnRun trigger and running the codeunit.

What is a Temporary Table? A Temporary Table is created by C/SIDE when a record variable is created that has its temporary property set to yes. It is created with the same exact structure

1-18

Navision Attain Solution Development

of the real table that is in the subtype property of the record variable. It is, however, completely empty (no data). This can be used as a temporary workspace to insert records, manipulate them and then either put them into a real table or allow them to disappear. No data in a Temporary Table will ever be stored on the server. To save records that are in a Temporary Table to the server, you must copy them to another record variable that is not tied to a temporary table.

Example of Using a Temporary Table The following code uses two record variables. Customer is a regular record variable that points to the real customer table. CustTemp is a record variable that points to a temporary copy of the customer table. Both have their subtype set to Customer, but CustTemp also has its Temporary property set to Yes. You can type in this code to see what it does. Customer.FIND('-'); REPEAT IF Customer.Name > 'F' THEN BEGIN CustTemp := Customer; CustTemp.INSERT; END; UNTIL Customer.NEXT = 0; FORM.RUN(FORM::"Customer List", CustTemp);

Multilanguage Functionality Navision Attain now has Multilanguage functionality. This section will cover what will be needed to enable this new feature. The Name property of an object should always be English United States (ENU), but it should also never be visible to the user. In all references to the user interface, you must use the Caption property instead. Note Accordingly, you must be sure that anything you enter that will end up in the user interface must be ENU. You can run a test by selecting all objects in the Object Designer, clicking Tools, Language, Export, saving the file as a text file, and then opening that file in Notepad. There must be no other language code than A1033 for ENU in that text file. When referring to fields in a message, the code will refer to the caption rather than the name of the field. By using the FIELDCAPTION, the current caption of a

Complex Data Types

1-19

field will be returned as a string. The field property CaptionML must be populated to enable this functionality. The TABLECAPTION function can be used to return the table name. Shown below is code to return the caption of the Document Type field. SalesLine.FIELDCAPTION("Document Type"); Error messages and other messages must be entered as text constants in the C/AL Globals window, Text Constants tab. When creating a text constant C/SIDE assigns a unique ID, which will be used in your error message.

Once it has been assigned as a Text Constant, it can then be used in code: ERROR(Text001); Below is an example of using the FIELDCAPTION function within an error message. Text Constant 025 value is Please enter "Yes" in %1 and/or %2 and/or %3.

ERROR( Text025, FIELDCAPTION(Receive),FIELDCAPTION(Invoice), FIELDCAPTION(Ship)); Which when the code is run the error message translates into: Please enter Yes in Receive and/or Inovice and/or Ship.

1-20

Navision Attain Solution Development

1.5 Using Versions, Transactions and Optimistic Concurrency


Now that you understand record variables, you can really understand how to use the database features that the Navision Database has built in. In this section, we will cover how to actually implement these various features in C/SIDE and in your C/AL coding.

Navision Server is Version-Based This is completely automatic for Navision Server, and you really do not have to do anything to implement it. However, you must understand this if you are to understand the functioning of certain methods in C/AL. Whenever you start a "process" (see Section 8 Application Architecture), the current Version of the database is assigned to that process. This means that from the beginning to the end of the process, all of the data that is read is consistent with the version of the data that was read at the beginning of the process. The advantage is that, for example, if a Trial Balance report is started from the General Ledger, it will run through using one version of the database, being completely in balance and consistent, even if people are still making entries and posting on other workstations at the same time. Another example is in the case of a backup. Throughout the process of a Navision Backup, the user doing the backup is on the same version. Thus, when complete, the backup is completely internally consistent. Remembering that the data could be scattered throughout the database on multiple disk drives, you can see how important this would be. Suppose, another user posted a General Ledger transaction, and the debit was in the part of the database that was already backed up while the credit was in the part of the database that was yet to be backed up, the backup would be out of balance and useless. How does this work? Each record is marked with the version number of the process that created it. If there are multiple versions of that record, the one that a process will use is the highest version number less than or equal to the current version that was assigned to this process at the beginning. What happens when some other user posts while I am using a version? Whenever a transaction takes place, a new version of the database is created. However, the old version is still kept as long as possible. As long as a session is

Complex Data Types

1-21

using a particular version, those parts of the database are not discarded, even though a new version exists. This is why it is so important to keep a good amount of free space in your database at all times (at least 20%). This "free" space is not unused; it is just available for new versions. At a bare minimum, the version that the posting process was assigned at the beginning must be maintained until the end, in case of a rollback. If there is not this much available space, the posting will fail. In addition, if a user is running a long report and needs to keep a version, but another user's posting process needs the space, the posting process will get the space, and the report will get an error saying that there was not enough space.

All Navision Updates are Transaction-Based This is almost as automatic for Navision Server as Version Based, but there are a few things you need to watch if you want it to work as expected. In order to update the Navision database, a transaction must be started. This starts a new version for each table that is updated. This version, however, is not available to anyone else on the system until the transaction ends. The transaction can end in one of the two ways. First, if it is completed successfully, it is committed (using an implicit or explicit COMMIT statement). This sets the current version of the database to the new version created for this transaction, and the space used by the old version becomes available. Second, if it fails due to an error, it is rolled back. This leaves the current version of the database whatever it was, and the space used for the new version becomes available. As you recall, transactions are started during a process when a LOCKTABLE function is executed, either explicitly or implicitly whenever a table is updated. From then on through the rest of the process, that table is using the new version currently being created. Any other tables that have not been locked or updated are still using the version in effect when the process started. Again, this keeps everything consistent throughout the posting process even if somebody else changes things like posting groups while you are in the middle of posting. When a table is locked, a new version is being created for that table. Every record inserted or modified will get the new version number. Nobody else can access that version and nobody else can lock the table.

1-22

Navision Attain Solution Development

Anybody else who starts or is continuing a process, will use the current version or the version in effect when they started. Anybody else who tries to lock the table, will wait until the table is available to be locked, and then lock the table and create a new version. At that point, they will "see" everything that everybody else did to the database since they started the process. Until that point, the only thing they could "see" in that table was the version that was current at the start of the process. For this reason, it is very important that you explicitly lock a table (using LOCKTABLE) before you "look at" (GET or FIND) any records from that table on which future updates will depend. Here is an example: Suppose you read the last record of a Ledger table to determine the highest Entry No. in it in order to make sure that the record you insert has an Entry No. one higher than that. Then you INSERT your record. Everything should be fine, right? After all, what can happen between two lines of code? Well, everything is not fine! Unknown to you or your process, when you started this, somebody else was in the middle of a 5-minute posting of the General Journal. Thus, your process was reading the most current version of the data, 4 minutes old. When you read, you got the highest Entry No. at that time (basically at the same time as the posting process started since nobody else can create a version either). Then, when you did your INSERT, an implicit LOCKTABLE was performed, and your process sits and waits for the other process to finish with the table. When the other process is completed, it makes its new updated version the current version. When you lock, you will now see this new version. In this new version, 2,000 more entries have been posted, and so the Entry No. you are trying to insert is no longer unused. You will get an error saying that you tried to insert a duplicate Ledger entry. What you should have done is an explicit LOCKTABLE before you did your read. In this situation, your process would sit and wait until the other process finished at the LOCKTABLE command. Then, you would see the new updated version before you read. The read would get the highest Entry No. in the most updated version in the entire database - the one you are currently creating. Now, when you add one to that number and use it to insert a new record, you are guaranteed that you will not get a duplicate ledger entry.

Navision uses Optimistic Concurrency First of all, what do we mean by Optimistic Concurrency? This means that we do

Complex Data Types

1-23

not lock a record before we read it for an update. Instead, we leave the record unlocked while you view it, and only lock it when you are ready to update. If you don't update, we never have to lock it. If you do update, and nobody else has edited that record, then we are fine. It is only if somebody else has updated the record while you were viewing it that we would get an error telling us that. That is why it is called "optimistic". We don't lock it in the optimistic hope that we will not get in trouble by not doing so. With a Version Based database using Transaction Based updates, and automatically locking the entire table (not just one record) whenever we update a record, how can we say that we use Optimistic Concurrency? Well, it is true that in code you must actually do something special to implement optimistic concurrency. However, in the most-often used database updates in the system, updates done by users using forms, optimistic concurrency is the automatic process used. Here is how Optimistic Concurrency is implemented. The situation is that it will be a long time from the time you read a record until the time you need to update it, and you do not want the table locked that whole time. First, you would read the record or records without locking. Then later, when you were ready to update, you would do an explicit LOCKTABLE, with the VersionCheck parameter set to TRUE. Then, you would do your record updates (reading and writing any records you wish). If no other process modified those records, you will complete successfully. If not, you will get an error telling you that somebody else updated the record. This is the same error you would get if you were editing a record in a form and somebody else updated it before you finished editing. How does this work? Recall that whenever a record is modified, it gets the version number of the process that modified it. Once you do the LOCKTABLE with the VersionCheck parameter set to TRUE, every time a record update is done, the record's version number is checked. If it is still less than or equal to the version number of the process, the update can go through without error. However, if it now has a higher version number than the process, that means that somebody else updated it since the process began and the error is generated. During all form updates, an implicit LOCKTABLE with the VersionCheck parameter set to TRUE is done first. Thus, for most purposes of any interest to the user, Navision Attain uses Optimistic Concurrency. For an example of Optimistic Concurrency in code, look at any of the "Post Batch" journal posting routines. Throughout the posting process, we read the

1-24

Navision Attain Solution Development

journal table so we know what to post. However, we do not lock it, so that users can continue to make journal entries in other journal templates and batches. At the end, when we are ready to update or delete the journal entries, we do a LOCKTABLE with the VersionCheck parameter set to TRUE. As long as nobody else was editing this particular journal or batch, everything will go through without error. Otherwise an error will occur and the entire posting will be rolled back.

Notes Concerning the SQL Server Version of Navision There are a few differences between the SQL Server database and the Navision Server database that you should be aware of. First of all, SQL Server is not version based. This means that if it is important for your report that it be consistent from beginning to end, then the only way to insure that is to lock the tables that you use for your report. We will do this for you in Account Schedules (financial statements), and a few other reports that we consider critical, but you will need to make these changes for any report your client considers critical to be internally consistent. SQL Server does not have a backup issue. You will no longer use the Navision Backup since SQL has its own built in backup procedure. The SQL backup will guarantee internal consistency by backing up the entire database and then backing up the transaction log containing all the transactions that have occurred since the backup started. Second, SQL Server handles optimistic concurrency differently than Navision Server. This will be handled in the forms automatically and we will modify the code appropriately for the posting routines. You will be able to see what we did when we release it since it will be conditional, based on which Server the application is attached to. All SQL Server updates are Transaction Based. Although it is implemented differently from the way Navision Server implements it, it will make no difference to the C/SIDE developer.

Complex Data Types

1-25

Chapter Review
1

Describe the difference between a simple and complex variable.

When can the Scope operator (" :: ") be used with complex datatypes? Give an example.

The GET() function requires parameters containing what?

What does the VALIDATE() C/AL function do?

What should you do prior to using the SETRANGE or SETFILTER functions?

This function clears all fields, filters and resets the key to the primary key _________________

This function clears all Filters and all fields except the primary key fields __________________

This function only clears filters and changes the key back to the primary key _______________

1-26

Navision Attain Solution Development

Chapter 2 Coding in Tables, Reports and Dataports

This chapter introduces the concept of triggers. It explains how to use the triggers found in Tables, Reports, and Dataports. Now that you know what code to write to perform most tasks, you need to know where to write that code. There are many places where you can place code. However, there is usually only one correct place. This chapter will cover the following sections: 2.1 What is a Trigger? 2.2 Table and Field Event Triggers 2.3 Report Event Triggers 2.4 Special Report Functions and Where They Belong 2.5 Processing Only Reports 2.6 Dataports Event Triggers Chapter Review

2-2

Navision Attain Solution Development

2.1 What is a Trigger?


There are three kinds of triggers that you can see in C/AL:

Documentation Trigger The first is the Documentation trigger. This is not really a trigger and there is not really C/AL code in it. Instead, a programmer can use the Documentation trigger to write any sort of documentation they want for the object. You will use this space to document your modifications to standard objects. Every object has a Documentation trigger.

Event Trigger The second kind of trigger is an Event Trigger. The name of these triggers always starts with On. The C/AL code in an event trigger is executed when the named event occurs. For example, the code in the OnRun event trigger of a codeunit is executed whenever the codeunit object is run. In cases where there is no trigger code, nothing would happen. Each object has its own set of predefined event triggers that can be programmed. An event trigger is a place for the Developer to respond to some event or action that has taken place in the system. These events are usually caused by the User clicking with the mouse or typing on the keyboard. This is the subject of this Chapter.

Function Trigger The third kind of trigger is a Function Trigger. These triggers are created whenever you create a function within an object. The C/AL code in this function trigger is executed whenever the function is called. You will learn more about creating and calling functions later in this course.

What causes an Event Trigger to Fire? The code in an Event trigger is executed by the Fin.EXE program when a specified event happens. When the user leaves a field, presses F3, or closes a form, Event Triggers fire. An Event Trigger is a term that is used with Event Driven programming. The term fire is used because the trigger code is not called in a linear or structured programming fashion. Code in an Event Trigger should stand

Coding in Tables, Reports and Dataports

2-3

completely alone. It should not depend on some prior event occurring. The User is usually in control of these events. The programmer cannot decide what event should come next or prior to another event. This is of course only a general rule, but is a good one to keep in mind when doing Event Driven programming.

Which Objects have Event Triggers? In Navision, all objects (Tables, Forms, Reports, Dataports, Codeunits) have Event Triggers. The type of the object determines what types of Event Triggers it has. A form object has many more Event Triggers than a table. A report object has many Event Triggers as well, but they a separated by the different sub-objects.

2-4

Navision Attain Solution Development

2.2 Table and Field Event Triggers


There are four events that fire for a table object. There are also two event triggers for every field in a table. In this section, you will learn when these events take place and how you can use them.

Table Event Triggers All of the table event triggers fire before the corresponding action takes place, i.e. the OnInsert trigger will fire before the record is ever inserted into the database. For each table event, C/SIDE provides two record variables for you to use. One is called Rec and can be considered the current record for the event. The other is called xRec and can be considered the previous version of Rec. These two record variables allow you to view the current record and make any needed changes. They are described in more detail for each particular event.

OnInsert The OnInsert trigger fires when the user inserts a record or the INSERT method is called with a parameter of TRUE. On a typical form, the insert does not occur until the user successfully leaves the Primary Key fields that are displayed on the form. If no Primary Key fields are being displayed on the form, the insert will be delayed until at least the record is changed. Although running a table creates a temporary form for you, this temporary form has delayed insert turned on. When delayed insert is turned on, a record is not inserted until the user leaves the entire record. During this event: Rec is the record that is about to be inserted into the table. xRec is the last record that the user was on before they press F3.

OnModify The OnModify trigger fires when the user modifies a record or the MODIFY method is called with a parameter of TRUE. On a form, the modification does not occur until the user leaves the record.

Coding in Tables, Reports and Dataports

2-5

During this event: Rec holds the value of the fields that are about to be put into the database. xRec holds the previous values of the fields before the user changed the record.

OnDelete The OnDelete trigger fires when the user deletes a record or the DELETE method is called with a parameter of TRUE. On a form, the delete does not occur until the user presses F4 and clicks the Yes button on the confirmation dialog (there is no confirmation dialog on records deleted in code). During this event: Rec holds the value of the fields that are about to be deleted from the database. xRec holds the previous values of the fields before the user changed the record.

OnRename The OnRename trigger fires when the user renames a record (this involves changing any of the Primary Key fields) or the RENAME method is called (this trigger is always called). On a typical form, the rename does not occur until the user changes the Primary Key fields and leaves them. During this event: Rec holds the value of the fields that are about to be put into the database. xRec holds the previous values of the fields before the user changed the record.

Field Event Triggers Every field in a table has its own event triggers. Within these triggers you also have access to Rec and xRec. There is also a new system variable provided for you called currFieldNo. It is described in details below.

2-6

Navision Attain Solution Development

OnValidate The OnValidate trigger fires when the user changes a field and leaves that field. This trigger fires before any other trigger can occur, like the OnModify, OnInsert, or OnRename (this includes form triggers that we will discuss later). You can use this trigger to make sure what the user entered into this field is valid or to populate other fields with values based on what the user entered here. This is probably the most commonly used trigger in Navision. During this event: Rec holds the values of all the fields that the user has changed or not changed. xRec is identical to Rec except that it holds the previous value of the field currently being edited. CurrFieldNo is set to the Field number of the field that the user changed. If the fields validate trigger is called from some other fields validate (originally initiated by the user), currFieldNo will be equal to the field number of the field the user originally changed. If the validate was called from code and not as a result of the user changing a field, CurrFieldNo is zero.

OnLookup The OnLookup trigger fires when the user clicks on the lookup button for that field. Any code whatsoever in this trigger (even comments) will cause C/SIDE to run only that trigger and ignore the default lookup that could have been set up by a table relation. For most fields this trigger is not used for that very reason. Most lookups in Navision are done via a table relation. This trigger, however, does allow the developer to write code for a custom lookup feature.

Activity In this activity you will put messages into the triggers above to see when they fire. 1 2 Design the Price Group table 6. Add a unique message to each table event trigger. Example Message(OnInsert);

Coding in Tables, Reports and Dataports

2-7

3 4 5

Run the table and note when each fires. Run the Price Groups form 7 and note when each fires. Do the same for the Name field.

2-8

Navision Attain Solution Development

2.3 Report Event Triggers


Reports have many triggers that are divided up among the many components of the report. There are triggers for the report object itself, for each data item, for each section, and for the request form. This section ignores the form triggers for the request form, because form triggers are discussed later.

Report Object Event Triggers To view these triggers you must click View, C/AL Editor while the report object is selected.

OnInitReport The OnInitReport trigger fires when the report object itself is created. This trigger fires before any other code in the report takes place, and even comes before the Request Form is displayed to the user.

OnPreReport The OnPreReport trigger fires right after the user closes the Request Form by pressing OK/Print/Preview. This trigger will not be called if the user cancels out of the report.

OnPostReport The OnPostReport trigger fires right after the last un-indented DataItem processes its last trigger. This signals the end of the report after everything has been printed.

DataItem Event Triggers To view these triggers you must click View, C/AL Editor while the data item is selected. Each data item has its own set of these triggers.

OnPreDataItem The OnPreDataItem trigger fires each time the DataItem is processed. This trigger fires before any records from the associated table have been read. This is a good place to set additional filters or even keys.

Coding in Tables, Reports and Dataports

2-9

You may also want to initialize some variables here that will be used to calculate values or totals for this DataItem (see the CREATETOTALS function later in this chapter).

OnAfterGetRecord The OnAfterGetRecord trigger fires right after the data item gets a record from the associated table. This is where most code will be placed in complex reports. This trigger fires before any printing for this record has been done (including headers and footers). You can skip records here if they should not be part of the report at all (see the SKIP function later in this chapter).

OnPostDataItem The OnPostDataItem trigger fires right after the last section for the processing of this DataItem has printed. This trigger fires each time the DataItem is processed. Note Only indented data items are processed more than once in a report. They are processed completely for each record that is not skipped in the DataItem that they are indented under.

Section Event Triggers To view these triggers you must click View, C/AL Editor while the section is selected. Each section of the report has its own event triggers.

OnPreSection The OnPreSection trigger fires right before the section is to be printed. This trigger is not for totaling or setting variables (for the most part). It is here to allow the developer to decide whether or not to actually print this section (see the SHOWOUTPUT function later in this chapter).

OnPostSection The OnPostSection trigger fires after the report has determined that this section will print and on which page it will print.

2-10

Navision Attain Solution Development

It actually fires before the section is printed not after. This is probably the least used trigger in a report.

Coding in Tables, Reports and Dataports

2-11

2.4 Special Report Functions and Where They Belong


In this section, you will learn about functions that you can only use in reports. These functions help you create complex reports. All of the following functions must be prefixed with CurrReport. (without the quotes).

Skipping Something in the Report The following functions allow you to skip some or all of a report.

CurrReport.SKIP Use this function to skip the current record of the current data item. If a record is skipped, it will not be included in totals and it will not be printed. Skipping a record in a report is much slower than never reading it at all, so use filters as much as possible.

CurrReport.BREAK Use this function to skip the rest of the processing of the DataItem that you are currently processing. The report will resume processing the next DataItem. All DataItems indented under the one that caused the break will also be skipped.

CurrReport.QUIT
This function skips the rest of the entire report. It is not an error, however. It is a normal ending for a report. Examples IF Amount = 0 THEN CurrReport.SKIP; IF ReachedMaximum THEN CurrReport.BREAK; Grouping and Totaling Functions The following functions make the report create totals or help when grouping a complex report.

CurrReport.CREATETOTALS Use this function to maintain totals for a variable in the same way as totals are maintained for fields by using the TotalFields property. This function must be

2-12

Navision Attain Solution Development

used in the OnPreDataItem trigger of the data item on whose sections you will be displaying the totals.

CurrReport.TOTALSCAUSEDBY Use this function to determine which field caused a break to occur. The return value is the field number of the field that the data item is grouped on that changed and caused a Group Header or Group Footer section to print. This function is almost always used in the OnPreSection trigger of Group Header and Group Footer sections. This function must always be used when grouping more than one field for a single data item. Examples //Report has 2 data items //Customer // Cust. Ledger Entry (indented and linked) //In the OnPreDataItem for Customer... currReport.CREATETOTALS("Cust. Ledger Entry".Amount);

Changing the Printing of the Report The following functions change the way that the report would normally print or give you information about how it will print.

CurrReport.NEWPAGE Use this function to force a page break when printing a report. This is usually found in the data item triggers.

CurrReport.PAGENO Use this function to return the current page number of a report and/or to set a new page number.

CurrReport.PREVIEW Use this function to determine whether a report is being printed in preview mode or not.

Coding in Tables, Reports and Dataports

2-13

CurrReport.SHOWOUTPUT Use this function to return the current setting of whether a section should be outputted or not, and to change this setting. This function should only be used in the OnPreSection trigger of a section. If TRUE is passed to the function, nothing changes and the section will print as normal. If FALSE is passed to the function, the section will not be printed for this iteration of the DataItem. Examples //In the OnAfterGetRecord Trigger IF StartNewOrder THEN BEGIN CurrReport.PageNo = 1; CurrReport.NewPage; StartNewOrder := False; END; //In OnPreReport trigger IF currReport.PREVIEW THEN ERROR('You cannot preview this report'); //In the OnPreSection trigger of a Body section IF ShowDetailSections THEN CurrReport.SHOWOUTPUT(True) ELSE CurrReport.SHOWOUTPUT(False);

MultiLanguage Functionality In order to enable Multilanguage functionality all reports MUST contain the following code in the OnAfterGetRecord() in the first DataItem: OnAfterGetRecord() CurrReport.LANGUAGE := Language.GetLanguageID("Language Code");

2-14

Navision Attain Solution Development

2.5 Processing Only Reports


A processing only report is one that does not print but instead changes table data. Printing reports can change records as well. This section applies to those reports as well. You can specify a report to be Processing Only by changing the Processing Only property of the Report object. The report will function just as it is supposed to (processing DataItems), but it does not print any sections. The Request Form changes slightly as well by removing the Print and Preview buttons and replacing them with an OK button (Cancel and Help stay). Below are some helpful hints when writing a processing only report. Change the ProcessingOnly property to Yes. Decide on the tables that need to be read these are the data items. Most of the code will go into the OnAfterGetRecord trigger. Dont forget the INSERT or MODIFY functions. Use a dialog to show the user the progress, and allow the user to cancel the report.

Activity In this activity you will create a processing only report that changes the prices in the item table. 1 2 3 Create a report with ID 99100 and Name Change Item Prices. Add two global variables Adj (integer) and Window (dialog). Add to the request form a text box and label. The sourceexpr of the text box will be Adj and the caption should be Adjustment Factor. Add the Item table as a data item. In the OnAfterGetRecord trigger, add code to change the Unit Price field of the item record to itself times Adj. Add code to display and update the window with the Item No.

4 5

Coding in Tables, Reports and Dataports

2-15

7 8

Add code to make sure the user enters a positive number. Test your creation. You may want to add a SLEEP to slow the report down.

2-16

Navision Attain Solution Development

2.6 Dataports Event Triggers


Most "real-life" Dataports require more work than just filling in the fields. Many times, they will require code, and that means triggers. Here are some of the triggers found in Dataports.

Dataport Object Event Triggers To view these triggers you must click View, C/AL Editor while the dataport object is selected.

OnInitDataport This event fires right after the Dataport is created and before the request form is displayed to the user.

OnPreDataPort This event fires after the request form is closed and before the data items are processed.

OnPostDataPort This event fires after the Dataport has finished importing or creating the file. All data items have been processed.

Data Item Event Triggers To view these triggers you must click View, C/AL Editor while the data item is selected. Each data item has its own set of these triggers.

OnPreDataItem This event fires before the data item is processed. It is a good place to set filters or keys for exports. It is also a good place to prepare the table before importing.

OnBeforeExportRecord This event fires after a record has been read, but before it is written to the file. This event only occurs while exporting data.

Coding in Tables, Reports and Dataports

2-17

OnAfterExportRecord This event fires after a record has been written to the file. It is a good place to reset the record variable or other variables being used. This event only occurs while exporting data.

OnBeforeImportRecord This event fires before the next record is read from the file. This event only occurs while importing data.

OnAfterImportRecord This event fires after a record has been read from the file, but before any AutoSave, AutoReplace or AutoUpdate has been preformed. This event only occurs while importing data.

OnPostDataItem This event fires after a data item has been completely processed.

Dataport Field Event Triggers To view these triggers, you must click View, C/AL Editor while the dataport field is selected. Each dataport field has its own set of these triggers.

OnBeforeEvaluateField This event fires after the field has been imported from the file, but before being assigned to the field or variable set in the dataport field's SourceExpr property. This event only occurs while importing data.

OnAfterFormatField This event fires after the value of the dataport field has been formatted, but before it has been written to the file. This event only occurs while exporting data.

2-18

Navision Attain Solution Development

Activity In this activity, you will create a dataport that exports and imports the customer table. 1 2 Create a dataport with ID 99100 and Name Customer Port Add the customer table as a dataitem and use the following fields as dataport fields: No., Name, Address, City. In the dataport field triggers, make sure the City field is uppercased before it gets written out to the file. In the data item triggers, make sure that when you import with this dataport, the Name field is validated. This sets the Search Name field. Run the dataport in CRONUS to export all the customers. Create a new company called TEST. Run the dataport in the new company to import the customers.

5 6 7

Coding in Tables, Reports and Dataports

2-19

Chapter Review
1 What function key is used to display trigger codes?

The __________________________ table trigger code is executed when a primary key field is changed and the user moves off of the record.

The __________________________ trigger code is executed when the value of any non-primary key is changed and the user moves off of the record.

Any code, even remarks, entered into the OnLookup trigger will (BE ADDED TO - or - REPLACE ) the internal lookup (F6) functionality.

TRUE or FALSE Execution of an ERROR statement in the OnDelete trigger will exit the table without actually having deleted the record(s) from the table. In which report trigger would it be most appropriate to place code that performs calculations on fields within a record?

Which report trigger contains code that is run before the Request Form is shown to the user?

What code would you use to keep the user from previewing a report? What trigger would you put the code in?

In which report trigger would it be most appropriate to place code that creates totals for a variable (CREATETOTALS) or adds further filtering for a DataItem?

2-20

Navision Attain Solution Development

10 In which report trigger would it be most appropriate to place code that informs the user of the completion of a non-printing report?

11

TRUE or FALSE The code in the OnPrintReport trigger is not executed if the report is a non-printing report.

12 You are creating a dataport to bring in student information. Because of the way data is stored in the data file, it is necessary to convert letter grades (A, B, C, D, F) into their Decimal equivalent (4.0, 3.0, etc.) for the Grade field. You decide to create a text variable called LetterGrade to hold the text data coming in from the text file. Write a CASE statement to do this and indicate the correct trigger for this code. TRIGGER: _________________________ 13 Concerning the previous question, how could you do it without creating a text variable but by sending the data straight into the Grade decimal field? Which Trigger would you use? TRIGGER: _________________________

Chapter 3 Object Analysis

To become an efficient and effective programmer in the C/SIDE environment of Navision Attain, you will occasionally have to leave this environment. This is especially true for upgrades, object analysis and many common tasks that are too time consuming to perform within C/SIDE. In order to work with objects outside of C/SIDE, you must export objects as text. A text version of an object can be confusing if you are not familiar with it. In this chapter, you will become more familiar with this format and understand the power that it gives the developer. We will also look at a tool that takes this format of your objects and breaks it down for easy analysis. The tool is Navision Developers Toolkit, and was created by a Navision Development Partner that worked closely with Navision a/s. This chapter covers the following sections: 3.1 Exporting Objects as Text 3.2 Editing an Object Using an External Text Editor 3.3 Changing the Text File 3.4 Object Analysis with Developer's Toolkit

3-2

Navision Attain Solution Development

3.1 Exporting Objects as Text


In this section, you will learn how to export objects as text to a file. You will also learn some important facts about the text version of an object.

Some Facts The are certain things you should keep in mind when working with the text version of objects: All objects can be exported as text. The text representation is complete. Every detail of an object can be easily seen and searched when exported as text. You can change the text object and import it back in as an uncompiled object. When you import text objects, you do not get a chance to see the import worksheet.

Basically, you need to be careful when working with the text version of objects. To export an object as text, follow these instructions:
1 2 3 4 5

Select the object or objects in the Object Designer. Click File, Export. Make sure to select the Text option. Select a filename. Click OK.

Activity Exporting an Object as Text In this activity, you will export the currency table as text.
1 2 3

Go to the Object Designer. Click the Table button. Select the Currency table (table 4).

Object Analysis

3-3

4 5

Click File, Export. In the Export window, put in a filename (you can use the Assist Edit button to bring up the File Save dialog). Make sure to give the file a TXT extension and to select the Text option here. Click OK to export the object to the file you have specified.

The file you create when you export as text is a Text file. You could open this with WordPad or Notepad, but if you have a true text editor like Codewright, you can customize the tool to work with Navision a little better. You will explore this more in the next section.

3-4

Navision Attain Solution Development

3.2 Editing an Object Using an External Text Editor


In this section, you will take a look at the object you exported and the different parts that make up the text version of an object. Note You can open these files with Notepad. This program is acceptable for small files, but for larger files you would have to use some other program. We recommend Codewright by Premia or some other robust text editor. Your class disk contains files for Codewright that will change Codewright to recognize the Navision Attain Object format and highlight keywords, literals and so on.

Activity Opening the Text File In this activity you will learn how to open the text file you created.
1 2

Using Windows Explorer, find the file that you exported in the last activity. Open the file by double clicking (this should open Notepad). You can also open the file using another text editor if you have it installed.

Object Analysis

3-5

Looking at an object in its text version To really understand what you will be looking at when you export an object as text, there are few things that need to be pointed out. Here is a sample of a table exported as text:
OBJECT Table 4 Currency { OBJECT-PROPERTIES { Date=08/21/98; Time=[ 2:00:00 AM]; Version List=US2.01; } PROPERTIES { OnModify=BEGIN "Last Date Modified" := TODAY; END;

Object Properties are the same for all types of objects: Date, Time, Modified Flag, and Version List.

The Properties section includes only properties that do not have the default value. Here only LookupFormID is

OnDelete=BEGIN listed. CurrencyExchRate.SETRANGE("Currency Code",Code); It also includes Trigger code. CurrencyExchRate.DELETEALL; END; OnRename=BEGIN "Last Date Modified" := TODAY; END; LookupFormID=Form5; } FIELDS { { 1 ; ;Code ;Code10 ;NotBlank=Yes } { 2 ; ;Last Date Modified ;Date ;Editable=No } { 3 ; ;Last Date Adjusted ;Date ;Editable=No } { 6 ; ;Unrealized Gains Acc.;Code20 ;TableRelation="G/L OnValidate=BEGIN CheckGLAcc("Unrealized Gains Acc."); END; } . . . { 12; ;Invoice Rounding Type;Option { 13; ;Amount Rounding Precision;Decimal

Then we have a list of the Subobjects, for tables that consists of Fields and Keys. They are grouped according to type. Fields in one bracketed group and Keys in another.
Account";

For each subobject (Field in this case), there is a list of properties and triggers. Notice
;OptionString=Nearest,Up,Down } ;InitValue=0.01;

that properties like FieldNo, Name and Data type are listed without the property name.

OnValidate=BEGIN IF "Amount Rounding Precision" <> 0 THEN "Invoice Rounding Precision" := ROUND("Invoice The brackets that are used Rounding Precision" END;

throughout the text version of

DecimalPlaces=2:5; an object are not the comment MinValue=0 } { 14; ;Unit-Amount Rounding Precision;Decimal; brackets that you would use InitValue=0.00001; in code. DecimalPlaces=2:5; They are used here MinValue=0 } like they would be in C or C++ { 15; ;Description ;Text30 } . . .

to note the beginning and ending of different areas. A comment placed in the code area does not affect the brackets here.

3-6

Navision Attain Solution Development

. . . { { { { 45; 46; 47; 48; ;EMU Currency ;Boolean ;Currency Factor ;Decimal ;Residual Gains Account;Code20 ;Residual Losses Account;Code20 } ;Editable=No } ;TableRelation="G/L Account" } ;TableRelation="G/L Account" }

} KEYS { { ;Code } CODE { VAR CurrencyExchRate : Record 330; GLSetup : Record 98;

After subobjects comes the CODE area. This area contains all the Global variables and functions.

PROCEDURE InitRoundingPrecision@2(); BEGIN GLSetup.GET; IF GLSetup."Amount Rounding Precision" <> 0 THEN "Amount Rounding Precision" := GLSetup."Amount Rounding Precision" ELSE "Amount Rounding Precision" := 0.01; IF GLSetup."Unit-Amount Rounding Precision" <> 0 THEN "Unit-Amount Rounding Precision" := GLSetup."Unit-Amount Rounding Precision" ELSE "Unit-Amount Rounding Precision" := 0.00001; Each Function can END;

have its own local variables

LOCAL PROCEDURE CheckGLAcc@1(AccNo : Code[20]); VAR GLAcc : Record 15; BEGIN IF AccNo <> '' THEN BEGIN GLAcc.GET(AccNo); GLAcc.CheckGLAcc; END; END; BEGIN END. } }

Note the extra begin and end here. This is where you would find the Documentation Trigger

Object Analysis

3-7

3.3 Changing the Text File


In this section, you will change the text file by adding a field and then import the file back into C/SIDE. You will discover what happens and what does not happen when you import a text file.

Activity - Adding a field The easiest way to add to the text file is to copy another part of the same text file and change a few things. That is exactly what you will do in this activity.
1

Find the Code field in the FIELDS section and copy that entire line to the clipboard (Select the line and press CTRL+C). Go to the bottom of the FIELDS section (just above the KEYS section). Just before the final curly brace that ends the FIELDS section paste the line you copied (CTRL+V). Renumber and rename the field. Use the name New Field. Save the file and exit the text editor. Open Navision Attain, open the Object Designer. Click File, Import. Choose the file you just changed. Click OK to import the file.

2 3

4 5 6 7 8 9

Note There is no import worksheet for Text files. The objects within the file will be imported directly and overwrite any existing objects with the same number. The objects will also come in uncompiled.
10

Find table 4 (Currency) in the Object Designer. Notice the value of the Modified flag and the Compiled flag. Press F11 to compile table 4 from the Object Designer (this compiles all objects that are selected in the Object Designer). Design table 4 (Currency) and see if your field has been added. Close the table designer.

11

12 13

3-8

Navision Attain Solution Development

Why Do This? Sooner or later, you will find out that you either have to manipulate objects in their text version to accomplish some task or you will realize that some tasks can be made much simpler by manipulating the text version. To use many of the tools that Navision Attain gives you, you need to understand the text version of objects. Thats even true of the next tool you are going to see Developers Toolkit.

Example Renumbering objects is much easier if you export all related objects as text and renumber everything in the entire file at once.

Object Analysis

3-9

3.4 Object Analysis with Developer's Toolkit


Have you ever had to increase the size of a text field in a database to allow users to enter more data? If so, you probably had to change quite a bit of code as well, perhaps even some forms had to change. Well, unless you are the sole programmer, its hard to know where throughout the program, changes need to be made. It may be some obscure code that manipulates that field using variables that now need to be bigger or it may be several forms that all display the field. It might even be a similar field in another table that should be increased because it can sometimes be assigned the value from the other table. In Navision, this can be a problem. The Developer's Toolkit, however, makes this task almost enjoyable. With Developer's Toolkit, the programmer can import a particular customers objects and make queries like Where is this field used (you dont actually type in the queries). You can even search the entire database for a word or phrase that you want to change. Unfortunately, right now the information that we can see in the Toolkit is readonly. Future versions will allow you to make changes directly in the tool. The following is an overview of the Developers Toolkit. The instructional Adobe Acrobat file is located on the Developers Toolkit compact disk handed out in class.

Some Facts Before you try to use the Developers Toolkit, there are some things that you should know about how the tool works. The Developers Toolkit takes the Text version of Navision Attain objects, parses everything out and stores the results into its own database. Everything you can see in the Developers Toolkit is read-only. The database that the Developers Toolkit uses to store its data is a Navision Attain C/SIDE database. This is NOT a Navision Attain database. The Developers Toolkit uses C/FRONT to read and write to its database. Future versions of the Developers Toolkit may allow us to change the objects and then put them back into the Customers database.

3-10

Navision Attain Solution Development

Installation Procedures
1

Install the Developers Toolkit.

The Developers Toolkit requires a separate installation than the Navision Attain Client. Because the Developers Toolkit uses C/FRONT, it needs to know the location of the client and the license file during installation (and will prompt you for this during the install). Therefore, you need to ensure the Navision Attain client is installed on the machine first.
2

Create a Developers Toolkit Database. You have to start Navision Attain to create and manage the Navision Developers Toolkit database. If you want to create a completely new database, you will need to: Start Navision Attain. Create a new Navision Attain database in the directory where you have installed Navision Developers Toolkit. If you want to import the object data of a standard Navision Attain application database later on, you should use at least 350 MB as file size for this new database. Open the Object Designer and import the file DevTool.fob from the directory where you have installed Navision Developers Toolkit. Create a new company. You can use different companies to store object data from different application databases in one Navision Developers Toolkit database.

Export Objects as text from a Navision Attain database. These will be the objects you would like to analyze in Developers Toolkit. They can be from any version of Navision Attain. You are required to export them as text so that additional information can be added to them when they are imported into Developers Toolkit.

Import the Objects into Developers Toolkit You can now import the text objects into the Toolkit tool. Just open Developers Toolkit, click File, Database, Open and open the database file

Object Analysis

3-11

that you have created. You should be prompted to open a company (If no Company exists, you must open the database with Navision Attain and create a company). Now you can click File, Import and select the text file that contains all of the objects you would like to import.

In the window above, you can assign a code to the objects you are importing (this is required) and a description (optional). On the Import tab you must specify the filename of the file you are importing. Once you input the above information, you can click the Import button. During the import, you will be given progress indicators that show you where it is in the process.

3-12

Navision Attain Solution Development

An import for an entire database can typically take anywhere from 5 to 15 minutes depending on the machine and number of objects.

The above picture shows the System Tab. It includes:


Field Name Date in Import File Description This field is filled in automatically when you enter the field Import Filename. You can see the date format of the first object in the import object file. Date Format Enter the date format for the date field in the import file. You can use your country specific shortcuts for day, month and year but you have to make sure that the delimiters are the same as in the field Date in Import File. Time in Import File This field is filled in automatically when you enter the field Import Filename. You can see the time format of the first object in the import object file. Time Format Enter the time format for the date field in the import file. You can use your country specific shortcuts for hour, minute and second, but you have to make sure that the delimiters are the same as in the field Time in Import File.

Analyzing Objects There are many ways to analyze your objects within Developers Toolkit. In this subsection, you will learn about all those different ways.

Object Administrator The Object Administrator window shows all objects that have been imported to the Developers Toolkit database. The Object Administrator is the backbone of

Object Analysis

3-13

Developers Toolkit. All activities are based on the data of the objects in the Object Administrator. These objects are grouped according to Navision Attain object types (Table, Form, Report, Dataport and Codeunit).

Object Views Object Tree this shows the result(s) of one or more functions in an Explorertype view. You can perform the same functions in the Object Tree as you can in the Object Administrator. Object Diagram this shows the result(s) of one or more functions in a graphical view. You can also use all of the functions in the Object Diagram as you can in the Object Administrator.

Object Functions Relations to Tables - this shows all table relations in the current object pointing to other tables. In Navision Attain table relations can be defined in the properties of table field and data controls. That means you can use this function for Tables, Forms, Reports and Dataports. Relations From Objects - this shows all relations from objects pointing to the current object. In Navision Attain, you can only define a relation to a table. Consequently you can only use this function for tables. Where Used - this shows all the places where an object or a part of an object is used. The Where Used function will search in properties and C/AL code of all object types. Where Used Options - You can set options for the where used function to either increase or limit the areas in the database it will search. Once the options are set they are then used for every Where Used function from that point forward.

Where Used With - this is the same as Where Used, but will present you with the Where Used Options settings. You can then set the Options for this use only, so that the setting do not effect other Where Used With functions run later.

Object Tools Object Bin - this shows an object in the same way as the Object Administrator, you can use the Object Bin to collect different Objects. You can also perform and function in the Object Bin as you would in the Object Administrator.

3-14

Navision Attain Solution Development

Code Viewer - this shows all C/AL Code lines for an object. The Code Viewer window is divided into two parts. The left side shows you the code structure of this object. For example you can see the list of object trigger, field trigger and procedures. On the right side you can see the C/AL code lines corresponding to the marked element on the left side. Keywords like commands are colored to improve the readability of the code lines. Source Finder - this searches the company for a specific character string. To specify where in the database the Source Finder must search, you can use the settings on the different tabs in the Source Finder window.

Compare Two Versions You can use the Compare Two Versions window to compare two versions that you have already imported in Navision Developers Toolkit. The comparison is based on the object structure and gives you fast access to specific areas. To create a new import version follow the steps below:
1 2

Start Navision Developers Toolkit. Click File, Database, Open to open a Navision Developers Toolkit database or click File, Server, Connect to connect to a Navision Developers Toolkit server database. Proceed as described in the following activity.

Activity Comparing Two Versions In this activity, you will compare two version of the Field of Dreams Project.
1

If you have not done the Field of Dreams Project, import it from the class disk located under labs/Day 4. Select all the objects in the Field of Dreams project and export them as text to a text file. Go into the Sponsor Table and add a field for Company. Set the table relation to the Customer Table. Go to the Pledge Table and add a field for Date Due. Export the Field of Dreams to a different text file. In the Navision Developers Toolkit, create the two versions and import the text files.

3 4 5

Object Analysis

3-15

Click Tools, Compare two versions. The Compare Two Versions window appears.

Each column shows you all objects of the versions you have selected in each column header. After you selected a version the comparison will start automatically. Both columns are synchronized vertical and horizontal and coloring is used to show the differences on all levels. When an item in a tree is not expanded, the item will represent the coloring of details of the item. If you want to set a filter on object type or object ID, you can click on the Functions button in this window.

3-16

Navision Attain Solution Development

Chapter 4 Development Methodology

When a Navision Solution Center (NSC) gets a new customer, it is generally because the customer can get their solutions customized to their specifications. As a result, there are almost always one or more development projects that need to be done, even before the product is implemented for the first time. In addition, as the customer's use of Navision Attain grows, they will often want additional customizations. In this chapter, we will cover how to do a customization project, working as a part of the Implementation team. This chapter covers the following sections: 4.1 Implementation Methodology 4.2 Version Control 4.3 Development Documentation

4-2

Navision Attain Solution Development

4.1 Implementation Methodology


As an important part of the training for a Navision Solution Center, Navision a/s teaches a specific way to sell, consult with, set up, install and maintain Navision Attain customers. We call this the Navision Implementation Methodology. As a Navision Attain Developer, you play a key role in two parts of this Methodology; Data Conversion and Customizations. Here is a more detailed look at the Navision Implementation Methodology. The ultimate result of using this methodology is a Navision Attain solution that fits the clients business, delivered on time and on budget.

Phases within the Methodology

The Navision Methodology uses a phased approach to implementation. Each rectangle in the chart below represents one of these phases, and they are described as follows:

Sales Phase The customer is not a customer yet. The Navision representative leads the process of assessing the potential customer's needs and how they can be met by the Navision Solution Center. This is where the contact decides to become a Navision Customer. Technically part of the Sales Methodology, the Sales Phase is tightly integrated with the implementation process allowing for a smooth, quick transition after the sale. Clearly defined sales deliverables, such as the Client Profile

Development Methodology

4-3

Worksheet, enable a clean handoff to the Implementation Consultant. The Critical Needs Assessment is a flexible process ensuring Navision is a good fit for the client. The size, complexity and risk of the project are factors that help determine the extent of the assessment. Certain key business challenges and needs are identified, and those are concentrated on. During this phase, the Developer will occasionally play a role in building a prototype as a proof of concept, or to answer technical questions. For the most part, though, the Developer is not involved in this phase.

Concept Phase From this point forward, we are working with a customer. They may not have made a product purchase decision, but they are at least a consulting customer. Unarguably, the Concept Phase is the most important phase in the process. With proper planning, analysis and design, the project has a much higher chance of being successful. Here, the customer's needs, including the Critical Needs, are defined fully, and the plans are made for meeting those needs. For example, decisions are made as to which Navision granules are to be purchased. Project Management guidelines for establishing project roles & responsibilities and communication methods, assure the project starts on the right foot. The Developer will work with and assist the Analyst / Consultant in two activities during this phase, Data Conversion and Customizations.

Development Phase All purchase decisions have been made; it is time to start implementation. The Development Phase includes the Detailed Design, Coding and Testing of modifications. It also includes the preparation of the User Documentation and data conversions.

Often, the development phase can get out of control from a time & cost standpoint, due to frequent changes or inaccurate estimates. The methodology contains tools to help manage the development. The Developer will take the lead during this phase for the Data Conversion and Customization activities. However, the Analyst / Consultant will still work with him, especially during the Detailed Design activity.

4-4

Navision Attain Solution Development

Infrastructure and Technical Setup Phase The Setup Phase includes the hardware and software installation and configuration tasks. The methodology contains many Setup Checklists that enable the clients staff to understand how and why the software is configured a certain way. The Developer will play a minimal role here, normally just to answer questions.

Training Phase End User Training can be executed using different approaches such as group training classes, one-on-one training or train-the-trainer. The Developer will play a minimal role here, normally just to answer questions.

Deployment Phase This is sometimes called the Turnover to the New System or Go Live phase. Successful Deployment depends largely on the previous phases; however, a Deployment Checklist is included that helps to assure all the important details are remembered. The Developer will play a backup role during this phase. They will normally only take part if something goes wrong at the last minute. Good planning and good testing will minimize this.

Roles in the Customization Activity Customization is a team effort. There are four roles to fill on this team. It is possible that you will have to play one or more roles in this process depending on your training, experience, special skills and the needs of the customer. However, for our purposes, we will concentrate on the Attain Developer's role in Customizations. The four roles are:

The Navision Implementer's Role The person filling this role is normally a graduate of the "Implementing Navision" course, a Navision Certified Implementation Specialist. He or she will lead the process of developing the customer's total solution. This is the key player in the Training and Testing phase of development. Also, once the Analyst / Consultant and the Developer have finished their jobs,

Development Methodology

4-5

the Implementer will actually install the customization at the user site. For an installation, this is normally done just before they "Go Live" with the new system.

The Customer's Role The person filling this role is normally the Controller or one or more other Key Users employed by the customer. He will work with the Analyst, the Implementer and the Developer to specify their needs for the system, approve of any customizations, interim and final testing of the results.

The Navision Analyst / Consultant's Role The person filling this role is normally also a graduate of the "Implementing Navision" course, and therefore a Navision Certified Implementation Specialist, although a senior Attain Developer, depending on the business practices at your NSC, can also fill it. This person will analyze the needs of the customer, match those needs with existing Navision functionality and determine which additional needs must be customized. He or she will work with the Customer to design the customizations, resulting in a Concept Document. They will also work with the Developer to design the customizations.

The Navision Attain Developer's Role The person filling this role is normally a Navision Certified Attain Developer. The Developer will get the Concept Document from the Analyst/ Consultant, and with his help, create detailed Design Specifications. He will then program the customizations, test them and deliver them to the Implementer for installation.

The Phases of the Customization Activity The process of customization involves almost every phase in the Implementation Methodology. Here is how those phases relate to the Development phases. Throughout all phases, project management practices apply. The developer, like all project participants, must be concerned with and follow team practices with regard to the management of work scope, time, cost, risk, communication, quality and customer satisfaction.

Project Orientation From the standpoint of the Solution Center and the Customer, the whole

4-6

Navision Attain Solution Development

customization work, indeed the entire implementation, is one project. However, from the development point of view, a Project is a smaller entity. For development purposes, a "Project" is a set of development tasks whose results will all be delivered together. In other words, all of the parts of one project are deployed at the same time, and before that time, no parts of the project will be deployed. During the Concept Phase, a list of customer Requirements will be developed. Each development project will implement one or more Requirements, each of which is either one feature, or a closely related set of features. Each of these development projects will be delivered separately, possibly at different times.

Phase 1 The Concept Phase During the concept phase, Navision Consultant(s) interview selected client personnel. The client is also asked to provide representative documentation of legacy systems and may be asked to schedule and participate in group sessions for gathering requirements. Using the information provided by the client, the consultant produces for the client, a detailed document describing the requirements in detail and a conceptual design of the solution. This document defines the functionality required to meet the client needs and highlights specific functionality that will require Navision software modification. From this "Concept Document", the consultant develops a cost proposal that includes detailed pricing for hardware, software, media and other Navision solution components. This proposal also includes a high level quote for services such as training and system modification. The system modification quotation is subject to revision after the design is completed.

The Focus study It is also important to note that the concept phase may be performed as one complete project phase or as two phases. In the two-phase approach, a concept document, known as a Focus Study is generated for the 2-3 most critical areas to the customer. From this, the client and the NSC will decide whether to go forward with the rest of the concept document. The client always approves the complete concept document before proceeding to development. The Developers Involvement. It is important that the developer participate in the development of the concept document. Experienced consultants may limit this involvement to reviewing the conceptual design and providing a cost estimate for customization. Less

Development Methodology

4-7

experienced consultants may need technical advice from the developer throughout the concept analysis phase.

The Conceptual Design Estimate Normally, the price for the development work is not provided as a fixed bid at this point. However, it is important that the estimate be higher than the revised estimates that will be provided after detailed designs are complete. This way we put ourselves in a position to beat expectations. Provide a worst case estimate and include contingency for risks such as lack of a detailed knowledge of what is required, modification complexity, area familiarity, developer experience and industry experience.

Conceptual Design Review When reviewing the conceptual design, keep in mind that the consultant is probably not a developer. Challenge the design if there is a lower risk way to solve the clients problem, especially one that will avoid development. Also, make sure that there is nothing in the requirements that will involve development that wasnt flagged.

Conceptual Design Tips The Requirements need to be defined prior to developing the conceptual design. Each requirement is separately numbered. A conceptual design must be presented for each requirement. Once the developer is involved, he may need to talk with the key users and managers within the client organization to get a clear picture of particular requirements. The next step is to decide how you will address the clients needs with Navision Software. Again, you need to do this for each requirement. Here are some of the possibilities, in order of ease of development:
1

Already Included - The need can be addressed by Navision software without modification. Perhaps all you need to do is see that they purchase the appropriate granule(s) and specify how the software will be configured to provide the solution. Available Code- The customer may have a need that can be handled by an existing Navision enhancement, an NSC developed Add-on, or objects and code from your own NSCs application library. In this situation, you will need to show the customer the solution and sell it to them. Even so, you still might need to customize it.

4-8

Navision Attain Solution Development

Minor Change - The customer wants pretty much what the base application or an add-on does, but just needs it changed a little. Sometimes this means adding a field or two, sometimes it just requires a name change (to a table or field or label), and sometimes it means changing the presentation on a form or a report. These kinds of changes are easy to do and easy to maintain as long as you follow Navision guidelines. Brand New - The customer wants a feature that is nothing like what it provided with Navision software. You may be adding an entirely new module, or maybe just a new report. It probably will have to be integrated with Navision Attain, but does not require any modification of the base application or the add-ons. It may take a lot of work to create this feature, but when new releases of the base application come out, it will not take a lot of work to upgrade this feature (probably no work at all). It is important to follow Navision Attain architectural guidelines when developing these solutions. Major Change - This is what you want to avoid. The customer wants something that would require a major change to the base application. Not only is this going to be a lot of work now, but will also be a lot more work later when the base application is updated to a new release. Changes would be required to the posting routines, or to the basic table relations. If you find that this is what the customer needs, try to rethink it. Perhaps you can turn this into something brand new that you can integrate with the base application. Or possibly, with a little imagination and discussion with the customer, you can turn this into a minor change with special training. Of course, sometimes you are stuck, and you have to make a major change to meet the customer's needs. Just be sure to point out to the customer that this will be expensive now and expensive in the future. Perhaps the customer will come up with an alternative, once they see the cost.

The client will be asked to approve each modification for detailed design work. The concept document will then be modified to only include the approved modifications. Normally, some higher risk modifications will be postponed to a second project to follow the initial implementation. Once the Concept Document is approved, we can begin detailed design work.

The Add-on Option One additional consideration is whether you want to develop the solution as an add-on to be re-sold by other Solution Centers. This will require a serious discussion between you and the person responsible for strategy and marketing in your Solution Center. Market demand and risk are key considerations here.

Development Methodology

4-9

You must be familiar with the rules regarding the commercial Navision Add-on Program, have sufficient time for the extra effort involved, and possibly be willing to underwrite part of the development cost based on the expected returns from the product.

Concept Approval Client acceptance of the Concept Document signifies approval to go forward on setting up the system and performing detailed design for development work.

Phase 2 The Detailed Design Phase For development purposes, the Development Phase of the Implementation Methodology is broken out into two phases: the Detailed Design Phase and the Programming Phase. During the Detailed Design Phase, customizations are first designed and priced. If the client accepts the customization, then it is developed during the Programming Phase. Note that during the Development Phase, any Data Conversion routines are also developed. See section 17 for more information on this subject. A development specification and a detailed development cost estimate will be created for each product Requirement. These "Design Specifications" will be accompanied by a User Document, which includes instructions for using the enhanced functionality and an exercise that will serve as the acceptance test script for the customization and as a training tool. The Design Specification is developed by the developer for the developer and includes the estimate. The Navision Consultant normally develops the User Document. The Navision Consultant will conduct a walk-through of the specification and User Document with the clients key users. Each specification will be signed-off individually by a client key user who has completed Key User training. The Consultant and the Developer together will often times break up a large implementation into separate Development Projects, each of which can be delivered at a different time, or possibly at the same time. Each Development Project will consist of one or more Requirements. All the Requirements for one Development Project will be in the same Design Specification document, and all the Requirements for one Development Project will be in the same User Document.

The Design Documents The User Document must be readily understood by both you and your customer since this is the document that will serve as the User Documentation, training

4-10

Navision Attain Solution Development

manual, and customer acceptance test script. Make this as realistic and as much in context to the clients operation as possible. Do include in full detail what the customer will see on the screen and in reports, and how the customer will operate the features. Do not include any details on how it will be developed technically. It should provide: Descriptions of the look, feel, functionality and performance of the application. Installation and Setup steps. A description of the operating process required to execute the applications functionality. An exercise that illustrates the process and the expected outcome.

One important goal of the User Document is to get the client to object HERE to what we plan to do, not later after we have invested in development. Where the User Document describes WHAT will be constructed from the users viewpoint. The Design Specification details HOW the solution will be constructed from the developers viewpoint. The Design Specification: Serves as Instructions to the developer. Describes the business functionality to be provided. Describes all changes to be made to tables, forms, reports, dataports and codeunits in detail. Lists limitations including what you are not going to do. Lists customer responsibilities. Lists the objects to be modified. Includes a time estimate for the work.

Both documents must be complete and address what will and what wont be done so that when the customer approves these documents, there is nothing that is open to interpretation. These documents are written with the customer. For larger modifications, you

Development Methodology

4-11

will write, and then you will show the customer, get feedback, and adjust the documentation accordingly. And remember, be specific. There should be no ambiguities in these documents. They only cause trouble later.

Scheduling These documents may be delivered in series. That is, one may be delivered, then another, then another, and so on it is not necessary to have them all completed before beginning development on approved designs. The developer will need to work with the Navision Consultant to develop an efficient build schedule for the modifications. A consideration in developing this schedule is that two Specifications can be worked on at the same time only if they are entirely independent. In other words, they can only be worked at the same time if there are absolutely no objects that are changed in both.

Prototypes You might want to use a prototype as a tool to communicate a conceptual or detailed design. A prototype is an application that looks like what the customer wants, but which does not actually do anything. You might create tables, fields, table relations and forms, but you need not create any code. You can simply tell the customer what will happen when the development is completed. If the customer likes what you have done with the prototype, you might even include screen shots and such from the prototype in your Design Specification or User Document. However, do not let the prototype substitute for a design. You must still write everything up. Also, be careful when using a prototype to sell the remainder of the product as part of a Focus Study or Conceptual Design. Normally, a prototype should only be developed for this purpose if: The client agrees they will proceed with the project if the prototype successfully demonstrates the ability to satisfy the requirement. All competitors are required to supply a prototype. You have an experienced developer who can produce the prototype with little risk.

4-12

Navision Attain Solution Development

Design Review It is usually a good idea to review your design internally before presenting it to the client. Check to make sure your design: Addresses the requirements exactly no more and no less. Specifies a least-risk solution. Is appropriately designed for reuse. Follows standard Navision Standards and System Architecture. Follows Navisions coding standards (See Navision Publications). Follows Navisions Low-Impact design guidelines (see Solution Developer Course).

Note the areas of risk in the design and focus attention on those. If you do not have multiple developers to do this work but feel you need it, you might consider subcontracting this review to a solution center experienced with this type of development.

Customer Approval Once you have a complete project design, you can present it to the customer for approval. Focus the discussion on the User Document. You and the client need a signed copy. You should never begin development without written customer approval of your modification design. Programming of a customization begins immediately upon sign-off of the specification.

Programming Phase This is the "programming" part of the development project. However, you will notice that it is not strictly programming. There are many things to do before, during and after the actual programming. At the end of this phase, you will have a product that is ready for testing by the customer for installation on his system.

Development Methodology

4-13

Create the Development Database The next step is to create the Navision database that will actually be used to develop this project. There are two ways to do this. First, if this is the original implementation (first project) for this customer, you must create the database from scratch using the Navision Attain Product CD. Perform the following steps:
1 2

Load an untouched database from the Product CD. Download the Latest Improvements attachment for this release, expand it and import the object file (.fob) into your development database. Load any other Improvements from the Product Database. If there are any add-ons, import them as well. Note that if there are multiple add-ons and they conflict with each other (update the same object), you will have to resolve these conflicts before you can continue. Export all objects as text, and then import this text file into your Compare Tool as your base version.

3 4

Second, if this is not the original implementation for this customer, but is instead a follow-up project, you must start with the database that you ended with at the end of the last Development Project. If there have been changes at the customer site (either by you or by the customer), you must perform the following additional steps:
1 2

Go to your customer site. Select all modified objects. Using the steps described in the Deployment phase below, give them their own Version Tag and turn off the Modified Flag. Export these into an object file (.fob) and bring them back to your office. Don't forget to tell the customer not to make any modifications on their own until you complete the project. Otherwise, they may lose these modifications. Back at your own site, import these changed objects into the database that you ended with at the end of the last Development cycle. Now, export all objects as text, and then import this text file into your Compare Tool as your base version.

4-14

Navision Attain Solution Development

Program Finally, we can actually start programming! Some things to keep in mind - For Customizations, be sure to follow your Design Specification. If you find you cannot, then be sure to change the Design Specification to match your actual implementation. All development must be done at your own site, not at the customer site, especially not if the customer is already live. However, for lengthy development tasks, you should show the customer your progress once in a while (at LEAST every other week) so that you can get their feedback. Either bring it to them on a portable computer, or invite them to your site to show it. If you get some feedback, check the feedback against the User Document. If you did it differently than the User Document says, fix it. If not, you (and the Consultant) will need to decide what to do next: For a larger change (or even a small one) you could decide to record the request and add it to another project. A small change might be handled with a change order.

You must do your internal documentation and your Project Log (as described in the Documentation part of this section) as you are programming. Do not wait until you are finished and then try to do this after the fact.

Internal testing You may decide you need to perform a code review prior to performing testing. This is intended to make sure you followed sound coding practices. Whether or not you performed this review, you should always test each feature as thoroughly as you can as you complete it. Make sure your tests include the test exercises included as part of your User Document. You should be testing both to find bugs and to make sure that the results match the User Document. If you have the customer's license, be sure that at least part of your testing is done using the customer license. Also, be sure to include some "regression" testing in your process. This means to test the normal, unchanged features of the product, to be sure that they still work correctly after your customizations. Concentrate this kind of testing in the areas of the product that are at risk, particularly those that are being modified and also those that interface with those that are being modified.

Development Methodology

4-15

Considerations for Multiple Programmers Sometimes a project is big enough where you will have to have multiple programmers working on it at the same time. If you can possibly prevent this, do so. For example, you could have one programmer writing the Design Specification, while another programmer does the actual programming (coding) and a third does the testing. Once the first Requirement was designed, they could be working at the same time, without interfering with each other. Sometimes, you just have to have multiple programmers. If this happens, you should use the following procedures to avoid problems. The project should be designed so that different Requirements can be assigned to different programmers. If two Requirements are to be worked on at the same time, there must be no objects in common. If there are objects in common, then that part should be treated as a separate requirement and programmed separately before the other requirements are assigned and worked on. Appoint one developer to be in charge of the development database. When a programmer is about to start coding on a feature, give them a copy of this database and a list of objects they are allowed to change (the Design Specification should already contain this). When the programmer is finished (including testing), they should filter export all of these objects and give them to the developer in charge as an object file (.fob). The developer will then import these changed objects into the development database. There should be no conflicts since the programmer only changed the objects that he was assigned to. Don't assign the same object to two programmers! When that programmer is ready to work on the next feature, they should again get a fresh copy of the development database. This is because other programmers may have checked in their work in the meantime, and their next feature may depend on the other programmer's work.

User Documentation The Consultant should update the User Document during this phase as necessary. If you end up changing functionality, that will require documenting the changes. If you agreed to provide additional documentation, you should also do that during this phase. As each feature is completed and tested, the documentation for it should be written. This can include user manuals, on-line

4-16

Navision Attain Solution Development

help, training materials and other documentation.

Phase 3 The Testing Phase Up until this point, you have been testing the objects you have developed as you go. In addition, you have been getting feedback from your customer. However, we have now reached the point where we are ready for the customer to run the new software on their own, at their own site, for acceptance testing. This development phase generally takes place during the Training Phase in the Implementation Methodology and, indeed, this is the time for the Implementer to train the Key Users and other actual users in the new functionality.

Customer Acceptance Testing When the development phase looks complete, then bring the completed development database to your customer site. Set it up as local database for each person who needs to look at the completed system. Give the customer a short training course, and turn them loose on it for testing. Note that you are NOT installing this on your customer's server or on any of his live data. This is just for testing purposes. Also note that this testing must be done with the customer's license. If you have delayed ordering changes to the license for cash flow reasons, the delay is now over. Any testing done by the customer must be done with their license, so those problems with the license can be uncovered. Besides, you must never leave your developer's license or your Solution Center's license at a customer site for any reason whatsoever. A key client user who has been through key user training must perform the test. Have the key user walk through the test exercise in the User Document. The customer may find some bugs. If so, review them to make sure they are really bugs, that is the User Document test scripts will not run properly. Do not accept a change in requirements as a bug. Also, make sure all valid bugs are logged and tracked in the project risk/issues log and fix them at your site. Once rework is complete, bring the copy over again for further testing. It is usually a good idea to track bug rates and hour expenditures. Large numbers of bugs usually indicates a design, not a programming problem. Once the test executes as specified in the User Document, you should obtain client sign-off and move on to Deployment. Sometimes, the client waits until this point to decide they really wanted different functionality. If so, you should

Development Methodology

4-17

bill the client for your completed work and issue a change order to conduct new design and development work using the process described here. As with the design, you must get the customer to sign off on completion of the work so that you can then proceed to the Deployment Phase. You must not implement your changes in the customer's live system without this approval.

Phase 4 The Deployment Phase With development completed and approved on a Development Project, you are ready to install the new or modified object(s) on your customer's site. For live Navision customers, this step is the most critical, since you can affect the actual live data of the customer. Until this step, nothing you did could cause any permanent harm.

Getting Ready to Go On-Site Follow these steps to create the installation object file (.fob):
1 2 3

Select and compile all objects. Filter on all objects whose Modified flag is checked. On each filtered object, add the Version Tag (see the Version Control part of this section) to the Version List. Now, filter on all objects whose Version List contains the Version Tag "*<version tag>*" Remove the filter on the Modified Flag. Turn off (uncheck) the Modified Flag on all objects. Select all of the (filtered) objects. Export using the Navision Attain format into a file named <version tag>.fob. This is your Installation Object File. Save this permanently. While you still have all filtered objects selected, export using the Text format into a file named <version tag>.txt. OR Do a Show All (remove all filters), select all objects, and export using the Text format into a file named <version tag>.txt. Use this second alternative if the project was a large one and you are expecting another large project soon.

5 6 7 8

10

4-18

Navision Attain Solution Development

Now, import this text file (created using either method) into your Compare Tool and generate your Change Log into a file named <version tab>.log. Save this permanently.

At the Customer Site There are two methods of installing at the customer site. If the customer has never had a live Attain database installed on site yet, you will:
1 2 3

Make a complete backup of your development database. Bring the backup file (.fbk) to the customer's site. Install Navision Attain (both client and server) on the customer's server in the usual manner (see the Installation Guide for more info on this). Open Attain in local mode on the server. Create a new database. Be sure to make it large enough, as the customer will start adding live data after this point. Restore the backup you made of your development system. Exit the client. Then, start the server, pointing it to your customer's new database.

4 5

6 7

If the customer already has a Navision product installed, you must select a good time to do this installation. It can take a long time and nobody must be on the system the whole time you are installing it. Perhaps a Friday afternoon, continuing on Saturday. Also, before you show up, remind the customer that any changes that were made to their objects since you got them in the first place are subject to being lost (giving them a chance to back up or document). You and the customer can go over the list of objects that you changed so that they know which changes will be lost. Here are the steps you should follow:
1 2

Bring the Installation Object file (.fob) created above to the customer's site. Bring down the server (nobody must be on when installing any objects like this). Make a complete backup of the customer's database, either using the Navision Attain backup utility, or simply copying the entire database elsewhere.

Development Methodology

4-19

4 5

Bring up the customer's database using the client on the server machine. Go into the Object Designer. On the Menu Bar, select on File and then click on Import. Select the Installation Object file you brought with you. There may or may not be conflicts. Even if not, be sure to bring up the Import Worksheet dialog. Press the Replace All button. Then press the OK button.

The import process may take a while. Especially if you have added or modified any table keys, since these will all have to be rebuilt. By the way, if you want to install your project while retaining any changes that have been done to the customer's database, you must follow the same procedures as you would for an upgrade. This is covered in another section of this course. Once you have completed your installation, go into the Object Designer, select all objects, and recompile them. This will show any problems between the modified objects and the unchanged ones.

The Final Test Setup and System-wide Testing After installation, the Consultant will coach the client through the remaining product setup steps and, for new installations, once all setup work is complete, through the implementation of a short beta and cut-over. The developer should not be needed during these steps but should budget a few hours of time in case bugs are found during integrated system testing. If a bug is found during this phase, you will need to treat it exactly the same as if the bug were found before you installed. Again, be careful to make sure it is within the scope of work as described in the User Document. If it was serious, you should restore the customer's database from the backup you made. If not, let them continue to work, but it is still not considered installed. Go back, fix the bug(s) and re-install. Obviously this is a huge pain. But in reality, it should not happen, since you and the customer should have already thoroughly tested it.

Final Customer Approval The project is not considered complete until the customer has given final approval. However, this is due once all setup processes are signed off, all development is approved and all bugs are resolved. Usually, once you have final approval, you would bill and collect any remaining money the customer

4-20

Navision Attain Solution Development

owes you.

Phase 5 The Maintenance Phase This phase corresponds to the Ongoing Support Phase in the Implementation Methodology. There are two areas of concern for the Attain Developer.

New Customer Requirements You may not have implemented the entire customer Requirements yet. Or the customer may very well come up with new requirements. Each new Development Project is handled as described above. It is highly recommended that you not make "on the fly" changes at your customer site at any time. Even if it seems like it would be easy to do, it will cause problems in the long run. Better to keep it formal and keep everything well documented.

Updating for New Release Navision Software will also be working on improvements to the product. No matter whether it is a new release, a service pack or just a product improvement, you should try to keep your customers up to date with the latest programs from Navision. When any Product Improvement or Service Pack is released, look it over and see if it affects anything that your customer purchased. If so, schedule a time to install it. If not, wait to install until something else is changed which your customer purchased. Then install both. Never skip an Improvement or Service Pack completely. They must each be installed in order so that they all work together properly. The only exception is that a Service Pack generally includes all Improvements since the previous Service Pack or Release, so you do not need to install both the Service Pack and the previous Improvements. When there is a new release, you should try to upgrade the executables as soon as possible. The application can be upgraded on a scheduled basis when you have time. Normally, a new release will have many more changes and will require data conversion and so on. Of course, these update instructions only apply to those customers that are on the maintenance plan. With this plan, they get the new code and software for free, but still must pay the Solution Center to install the changes. There is more information on how to install upgrades in a later section of this course.

Development Methodology

4-21

4.2 Version Control


When you are delivering a product to a customer, you may have performed several modifications. You might have updated the objects with an improvement you obtained from Navision. You might have an add-on that you or some other Solution Center created. You have your own customizations for this customer. Plus, you might have changed the customizations for this customer. You have a lot to keep track of. This collection of changed objects is unique and you need to know where all of these objects came from, and that is not all. Suppose, that installing an add-on changed an object and customizing it for your customer further changed it. Now, what will happen when Navision releases yet another improvement that affects this object? How do you know which object can just be loaded on and which will take more work than that? It is for these reasons that you need a method of Version Control. Fortunately, in Navision Attain, there are various tools built into C/SIDE that will help you with your version control. But you must know how these features work in order to use them effectively. This is what we will be covering in this section.

Modification Flag The Modification Flag is a kind of automatic version control. Whenever you change an object, the modification flag is automatically checked. The only way it is unchecked is if you deliberately uncheck it. This is an excellent tool to use while you are in the process of developing a project. Then, once you have completed the project, you can select all of the modified objects and set the version tags (see below). Once you have done that, you can turn the modification flags off. This way, you can tell automatically if anything has been done to change the objects since the project was completed. If you make modifications at the customer site, or if the customer has the design tools, the modification flag is a good way of telling that changes have been made on site. Therefore, in either of these situations, it is strongly recommended that you do not uncheck the modification flag. One thing to watch out for - Occasionally, the only modification you make to an object is to change the object name, which you can do from the Object Designer. If you do this, the modification flag will not be automatically set (nor will the date and time stamps). Therefore, it is recommended that you actually call up the object (by pressing the Design button) and change the Name

4-22

Navision Attain Solution Development

property of the object. Then, when you save it, it will update everything automatically.

Version Tags The "version tags" are located in the Object List in the column called Version List. In order to work correctly with the Import Object utility within Attain, the version tags require a fairly standardized format. Therefore, first we must cover how the Import Object utility uses the version tags.

Import Objects
When importing objects, the Import Object Utility checks both the imported object and the matching object in the database, and checks both the Version List and the Modification flag. It considers the Version List to be a list of version tags separated by commas. Thus, NAVW13.00,NS01.01 is considered two version tags, the first is NAVW13.00 and the second is NS01.01. Let us first consider a Version List with only one version tag.

Existing Object: Modification Flag No No No No No No Yes Yes Yes Yes Yes Yes

Existing Object: Version Tag

Imported Object: Modification Flag

Imported Object: Version Tag

Result: Default Action

Result: Conflict

NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10 NAVW11.10

No No No Yes Yes Yes No No No Yes Yes Yes

NAVW11.00 NAVW11.10 NAVW11.11 NAVW11.00 NAVW11.10 NAVW11.11 NAVW11.00 NAVW11.10 NAVW11.11 NAVW11.00 NAVW11.10 NAVW11.11

Skip Replace Replace Replace Replace Replace Skip Skip Replace Replace Replace Replace

No No No Yes No No No No Yes Yes Yes Yes

Note that the Default Action of "Replace" is sometimes "Merge" when you are

Development Methodology

4-23

dealing with a Table Object. The situation with multiple version tags is similar, except that each version tag on the imported object is compared with its corresponding version tag in the existing object to discover the differences. If there is a version tag missing, it is considered to be an earlier version than one that exists. The first is compared with the first, the second with the second, using the above table. If there is a conflict with a version tag, then there is a conflict on the import. If any tag calls for a replace, the import calls for a replace.

Navision NTR usage Now this is how we use version tags at the Navision NTR level for the base application. The first version tag is usually the world wide base application. It consists of parts; if the version tag says NAVW13.10.01.25, the "NAV" is the product (Navision Attain), "W1" indicates that it is a world wide object, "3" is the major release, ".10" is the minor release, ".01" is the maintenance release (service pack), and the ".25" is the unreleased (but published) hotfix number. In all cases, before we publish a release or an improvement, we turn the Modification flag off. If a level is missing, for example, NAVW13.10, the numbers are left off. The major and minor release numbers are always present, but there may not be a service pack or hotfix as of yet. Since the import utility uses an ASCII compare (character by character), NAVW13.10 is considered earlier than NAVW13.10.01. Many objects are added at the NTR during our localization process. If a base application object exists only in one country, it can of course be recognized by the fact that its object number is in the country's special range. It can also be recognized by the version tag, which will say (for example) NAVUS3.10.01.25. Note that this is exactly the same as the version tag in the above world wide th th example, except for the 4 and 5 characters. The "W1", which indicated world wide, has been changed to "US" indicating that this base application object is from the United States. In addition to adding objects during localization, we also modify world wide base application objects during localization. In this case, there will be two version tags, one the world wide tag, and the second the NTR tag. For example, an object might have NAVW13.10.01.25,NAVUS3.10.00.02 in the Version List field. The first (before the comma) is the world wide version tag, and the second (after the comma) is the NTR version tag. For each other product we create (like Commerce Portal), we create a new version tag as follows: CPOW12.01.02.09, where "CPO" is the three letter product code, "W1" indicates it is world wide, "2" is the major and ".01" is the

4-24

Navision Attain Solution Development

minor release number, ".02" is the service pack, and ".09" is the improvement number. If a base application object is changed, we add the other product's version tag to the end of the base application version tag, separated by a comma. If this is a new object, we just use the other product version tag. In either case, we turn the modification flag off before we publish any product. If an NTR creates a separate product, the same rules will hold, except the the "W1" would be replaced by (for example) "US", indicating the NTR. Note that in our examples, each of these tags has a "US" in it, to indicate that it is a United States object. Each country in the Navision World uses their own twocharacter country code in their version tags, like "DE" for Germany, "UK" for United Kingdom, and "DK" for Denmark. The worldwide version of the application has its own two-letter code, "W1".

Attain Developer Usage Finally, here is our recommendation on how you should use these version tags. You should always leave our version tags alone! As you are making changes, you should leave the modification flag on, and only turn it off when you have created a new version tag and set all changes to that tag. Never turn the modification flag off unless you change the version tag. If you are making minor modifications at a customer site, you do not even need to create a version tag: just leave the modification flag on. If you are creating a major modification for a customer, then you should create a version tag for that customer. Use 2 or 3 characters to represent the customer and add a "00" (two zeroes) to it. Whenever your modifications are stable (working and you will not change it for a little while), you should filter on the modified flag set to yes, and add the new version tag to the Version List. If it is a base application object, separate your new tag from our existing one with a comma (no space). If it is a new object, just use your version tag (erase ours if you copied from one of our objects). Now, remove the filter from the modification flag, and add a filter to the Version List, which will be your version tag preceded and followed by an asterisk (e.g. *XYZ00*"). You can now turn all the modification flags off. Then, without removing the filter, select all objects and export them all into an fob file named the same as your version tag (e.g. "XYZ00.FOB"). When you make a major upgrade for your customer, you would perform the same steps, except that you would use the next number (e.g. "00" -> "01"). Any object that changed (even if it had never been changed before) would receive the new version tag. If one of the customer's version tags was already on the object, it would merely be changed to get the new number. If you are creating your own add-on product, a similar process would take place. The only difference would be that you would take the letters from your

Development Methodology

4-25

own Solution Center name, and the name of the add-on product, to create the version tag. Thus, like the base application, there will be a 3 letter add-on product code, followed by a 3 letter NSC code (not 2, since it might be the same as a country code), followed by the version numbers as needed. For example, if your NSC was named "Computer Technology Innovators", and your add-on was named "Bowling Alley Management", then the first version of this add-on might have a version tag of "BAMCTI01". Also, we would recommend bringing your working database up to the latest released version of Attain, including all published hotfixes, just before you put your version tags in. This way, any base application object that you have changed will get the latest base application version tags. Of course, if you have to apply the change log manually (since you already modified the base application object with your add-on), you must set our version tag manually as well. Don't forget to export all changed objects into a single fob file once you have set all the version tags and turned off the modification flags. This is the file you will probably ship out to purchasers of your add-on. When you are ready to upgrade your add-on product, take your original version tag and increment the number for each major release. If you are making a minor release, add a ".01" to it for the first minor release, ".02" for the second, and so on. Thus, your original add-on product described above might have a version tag of "BAMCTI01", the first minor modification would be "BAMCTI01.01" and the second would be "BAMCTI01.02". The next major release would be "BAMCTI02". When using multiple version tags, the order is quite important, since the import utility compares 1st with 1st, 2nd with 2nd, and so on. If the order on an imported object is different from the order on the existing object, the comparison will not be done correctly. On the other hand, if the order on one object is different from the order on a different object, that will not matter, since each object is compared individually. However, for consistency and ease of updates, we ask you to use the following order for version tags: Base Application version tags (first world wide, then NTR). Other Navision Product version tag. Add-On version tags. The specific order is unimportant, but should be consistent. We suggest the following: Other Solution Center Add-Ons

4-26

Navision Attain Solution Development

Your own Add-Ons.

Custom modifications version tag.

This is normally the order you would add them anyway, so it should be convenient. Here are some other examples: A released base application object from an NTR: NAVUS3.10 The same released base application object, with hotfix number 23: NAVUS3.10.00.23 The same object, with the 2nd upgrade of your add-on applied: NAVUS3.10.00.23,BAMCTI02 The same object, installed on your customer site and then customized for that customer: NAVUS3.10.00.23,BAMCTI02,XYZ01

Development Methodology

4-27

4.3 Development Documentation


In the above discussion, we talked about many different documents that the developer must look at and write. Let us go into more detail on each of these. There are several kinds of documentation that we will be describing here. However, they all have one purpose in common. This documentation is for the benefit of the Attain Developers. To be more specific, the developers will use this documentation for the following purposes: Organization - The Attain Developer, as part of the development process, must organize the changes to be made, and organize the implementation of them. Audit - To create a permanent record of what changes were made, who made them, when they were made, and why they were made. Communication - In projects where there is more than one developer, your documentation is what will keep everyone on track. Upgrades - When a new version is released, your documentation will be indispensable in upgrading your customization to the new version.

There are other kinds of documentation that you will be reading and may be writing as a Attain Developer. These include Concept Documents, User Documents, user manuals, proposals, quotes, and so on. These subjects are covered minimally in this class. We are concentrating on the documentation that is used strictly by and for the Attain Developers in your organization.

Project Orientation The documentation that you will write will be based on a project. When you are going through your Concept Document, you will first divide the job into various projects. Each project will implement one or more "Requirements" from the Concept Document, each of which has one feature, or a closely related set of features. In many cases, a set of modifications for a customer will become a single project. In some cases, the modifications are so extensive and complex that you will have to break the job into multiple projects. Each of these projects could be delivered separately and possibly at different times. Once you have determined what is included in your project, you will then write a Design Specification. This is not the User Document. A Design Specification is used by a developer and to communicate between developers. However, the customer will review this document and approve it.

4-28

Navision Attain Solution Development

Once you have a Design Specification, you will then start working on implementing your project. While you are doing this, you will be creating documentation internal to each object and you will be creating a Project Log.

Concept Document The Concept Document is a document created by the Navision Analyst / Consultant together with the customer, to specify the customer requirements and what the Navision Solution Center will do to meet those requirements. It will contain information on what hardware needs to be purchased, what Navision granules will be purchased, what customizations will be done and what other services will be done. For more information on developing this document, refer to the Implementing Navision course. For the developer, the most important things here are the requirements that involve customizations. Each Requirement has a section number (like 4.2.7) which is to be used as a reference in other documents to refer to the requirement in the Concept Document. Depending on your organization or experience, this document is the equivalent of a "Functional Requirements Document" or a "Project Specification".

User Document The User Document is a document created by the Navision Analyst / Consultant, together with the customer, to specify what will be changed in the product to meet the customer's Requirements. It goes into more detail than the Concept Document, in that it fully explains to the customer what is being changed, how it will look when it is done, and how the customer will run it once it is deployed. For more information on developing this document, refer to the Implementing Navision course. Like the Design Specification (see below), the User Document will have a different "chapter" for each individual customer Requirement that is being handled by a customization. The Requirement number used in this document is the same one that was used in the Concept Document, so that everything ties together. The developer should note that this document will often include "test scripts", which will be used by the customer to verify that the customization has been done correctly. The developer should be familiar with the contents of the User Document (and will probably help in developing it) so that he knows what the customer will expect when the customized product is deployed.

Development Methodology

4-29

Design Specification The Design Specification is a document created by the Navision Attain Developer, together with the Consultant, to specify the exact changes that will be made to the product in detail. It takes a different point of view than the User Document and Concept Document, since those are written from the point of view of the user. The Design Specification is written from the point of view of the programmer. As already mentioned, the Design Specification is used by a developer and to communicate between developers. Whenever you write a design specification, you should write it as though you were telling another programmer how to make the modifications, even if on this particular project you will be doing it all yourself. A design specification must be detailed and organized, and writing it will help you with your thinking process. Later, when you are trying to figure out a particular section of code, your design specification will tell you the why and how of that code. A design specification can be in any format that accomplishes the primary goals of organization and communication. However, we have a sample format which accomplishes these goals, without overdoing the details. You may use it and adapt it to your own purposes and style. On your class CD is a Word 97 template called "DesignSpecification.dot". The best way to use this is to copy into your Templates directory, usually found under "MSOFFICE" on your C drive. Once this is done, when you create a new document, it will appear as one of the templates and you can select it. Create a document using this template, and then follow along as we go through the various parts.

Document Properties The first thing you should do is fill in certain document properties which are used in the form itself. Using the Menu Bar, select File and then Properties. On the Summary tab, the following fields are used: In the Subject field, fill in the name of the project as a whole. This will appear on the cover page. In the Company field, fill in the name of your Solution Center. This will appear in the heading on every page. You may just want to fill this in directly in the template.

On the Custom tab, there is a table in the middle that lists the Name, Value and Type of the various properties. One of these properties is named "Client". Click on Client in the Properties table, and the Name, Type and Value will be displayed in the boxes above the table. Change the Value from "Customer

4-30

Navision Attain Solution Development

Name Here" to the name of your customer, and then press the Modify button. This name will appear on the cover page. Press the OK button to leave the Properties dialog.

Requirement Header Each Requirement in the project will get a separate section in the Design Specifications, each one starting on a new page. It is recommended before you start filling out a new section that you first make a copy of the last section, so that you always have a blank section on the end to use when creating the next Requirement. The title of the page includes the Requirement Number and Requirement Description. The number should be taken from the Concept Document section number where the Requirement is first described. The Description should be a 2 or 3 word title, just to identify the requirement. The other parts of the Requirement Header should be filled in as follows: The Summary field should have a 1 or 2 line description of the Requirement. The Status field should indicate the current status of this Requirement in one word. The Assigned To field should indicate the name of the developer in charge of this Requirement. The Hours Estimated field should be taken from the total in the Estimate part of this Requirement. The Estimated Labor field should be the amount you expect to bill for labor. It could be the number of hours estimated multiplied by an hourly rate, or it could be a fixed bid. The New Table Objects field should include the number of new table objects being added for this Requirement. The Other New Objects field should include the total of the number of form, report, codeunit and dataport objects being added for this Requirement. The New Object Cost field should be the cost to the customer of the above new objects. The Estimated Billing field should be the sum of the Estimated Labor and the New Object Cost fields.

Development Methodology

4-31

Don't forget that there is a major price break for buying 10 tables objects or 100 of any other Objects at the same time. If you can take advantage of a price break, prorate the cost of the objects over the entire project. For example, if you have 5 Requirements each requiring one table object, the normal cost of each table object would be $240. However, taking advantage of the price break of 10 tables for $720, the price allocated to each of the 5 Requirements for their table object would be $144, not $240. This is because the $720 price is divided among 5 tables. Note that the customer ends up with 5 unused table objects for future projects or for his own use.

Technical Specifications This is the actual detailed specification portion of the document. We have divided it into 4 parts to remind you of the information needed, but you can set it up any way that works in your organization. Here is where you get down to brass tacks. On an object-by-object basis, describe the changes that you will be making. Make sure you identify each object by type, by number and by name. If it is a new object, describe what it is for, what it will do, and what the programmer will do to create it. If it is an existing object, describe what the changes are, and what they are for. You obviously do not need to record the actual code changes (after all, you can always look at the finished object for that), but you should use sufficient detail that you could hand to an entry-level programmer and have them complete the programming correctly. Sometimes that means going into great detail, while other times it requires only one sentence to describe the changes.

Limitations Here is where you specify what you will not be doing, if that is necessary. You will also describe what parts of this are being left to the customer to do. If some functionality is being delivered in stages, state here what parts will not be available until another phase.

Estimate Once you have completed the Technical Specification, you ought to be able to give a fairly accurate estimate of what the hours will be to complete this work.

Impact on Upgrades This is where you specify what the impact of these changes will be when it comes time to install an upgrade. This is important as the customer figures out

4-32

Navision Attain Solution Development

the total cost of ownership. Include an estimated time to upgrade.

Approval Indicate to the customer how they should let you know that you can go ahead with your work. Some sort of written, signed approval is recommended. Once it is approved, attach the approval document(s) to the end and record here when it was approved, who approved it and where the approval document can be found.

Objects As you actually program the modifications, you should enter in this section, a list of the actual objects changed and created. Include the Object Type, Object Number and Object Name. If this is a modified object, indicate the base version tag before you made your changes otherwise indicate "New".

Attachments If there are any attachments at the end pertaining to this Requirement, include them here. If not, erase this part.

Revisions While implementing the changes you have described, you may find that you need to change the design. Should this happen (and it often does), you should revise the Design Specification to reflect these changes. When you finish, the Design Specification must match the program and the program must match the Design Specification. If the change affects the functionality, you will probably need to get customer approval to make the change. Try to keep these kinds of changes to a minimum. Whenever you make a revision to the Design Specification, create another Part at the end of your Design Specification, describing the change, when it was made, and why you made it. To facilitate this, you may want to take advantage of some of Word's capabilities in tracking changes to documents. Here is how: Save Original Version - Go to File, Versions, and press the Save Now button. Enter a description indicating that this is the original version approved by the customer.

Development Methodology

4-33

Track Changes - Go to Tools, Track Changes, Highlight Changes, and then check the box that says Track Changes While Editing. Make Your Changes Review - Print out the specification showing changes. Review with Consultant and/or Customer as necessary. Add Revisions Part - Add a new Part (using the Heading 2 Style) to the end of the Specification called Revision. (whatever revision number it is), and describe the revision in that part. Accept Changes - Go to Tools, Track Changes, Accept or Reject Changes, and accept all changes. Turn Off Track Changes - Go to Tools, Track Changes, Highlight Changes, and then remove the check mark in the box that says Track Changes While Editing. Save New Version - Go to File, Versions, and press the Save Now button. Enter a description indicating that this is a revision and which revision it is.

Internal Documentation By "Internal Documentation", we mean the documentation that is written directly into the objects themselves. These include code comments, the Documentation Trigger of each object and Description fields in the field definitions. Note that there is some difference between the internal documentation for a new object, and that for a previously existing object.

Documentation Triggers If you will look at the code within each object, you will note that there is a Documentation trigger as the first trigger within the object. This trigger is never executed, so it does not need to contain actual code. Instead, it is designed so that you can enter comments about the object as a whole there. The use of the Documentation Trigger for a new object (being created for this project) is optional. If you use it, you should do it the same way as described below for an existing object. The only difference is that the "sequence number" should be "00". For an existing object (one that was in existence before this project), you must create a heading in the Documentation Trigger, for each modification you make. Usually, this amounts to one per feature. This heading should contain some

4-34

Navision Attain Solution Development

sort of Reference Number, the date when the modification was completed, who did the modification (Solution Center Name and individual name), the project, and a short description of the change. Here is an example: NJD01 - Navision, John Doe, 02/12/00, Multi-state Payroll Added the new State and Locality fields. Modified the trigger code to default these fields whenever the Employee No. is entered. Note that the Reference Number (NJD01) is a combination of the initials of the Solution Center, the initials of the developer, and a sequence number. This sequence number should start with 01 for each object, so that the first modification of this object has the number 01, the second modification of this object has the number 02, and so on. The only exception is that, if this is a new object, the sequence number should be 00.

Code Comments There are many theories about how to comment your code, and for normal purposes (explanations, and so on), you should use whatever method you think is best. However, for our documentation purposes, you need to mark each modification with a comment using a special method. This should only be done when you modify an existing object, not when you create a new object. The key is to mark the changed code with the same Reference Number as you used in the Documentation Trigger of this object. For example, if you have modified a single line of code, you should mark it like this: State := "Employee."Default Work State"; // NJD01

If you have added or modified an entire block of code, you should mark your change as follows: // NJD01 Start State := "Employee."Default Work State"; Locality := "Employee."Default Work Locality"; "Work Type Code" := Employee."Default Work Type Code"; // NJD01 End If, as part of your modification, you have deleted a large block of code, you should mark this deletion as follows: { NJD01 Start Deletion State := "Employee."Default Work State"; Locality := "Employee."Default Work Locality"; "Work Type Code" := Employee."Default Work Type Code"; NJD01 End Deletion } Note that this will keep the old code in place, just commented out.

Development Methodology

4-35

If you have a standard method of commenting your code so that you can tell how the code works, or what it is doing, you should continue to use that method. This modification marking is in addition.

Field Descriptions Whenever you add a new field to an existing Table Object, or modify an existing field in a Table Object, you should mark that field with the same Reference Number that was recorded in the Documentation Trigger of that same object. Simply entering the Reference Number into the Description property of the field should do this marking. Do not do this if you are creating a new Table Object.

Project Log The Project Log is your record of everything that has been done for this customization project as a whole. It should be created while you are actually doing the modifications. Once you have completed your Design Specifications, you should create your Project Log as a plain text file and give it a header that contains the following information: Name of Project Solution Center Name of Project Leader Customer Date Started Date Completed Name of Design Specification document Version Tag Name of Change Log A short description of the project (remember, this information will already be in the Design Specifications).

4-36

Navision Attain Solution Development

The Project Log Heading can be in any format you want, but here is an example that you may use: Multi-State Payroll Customer: Acme Widgets Navision John Doe Date Started: 4/08/98 Date Completed: 4/23/98 Version Tag: NS012.01 Design Specification: multi-state.doc Change Log: multi-state.log Add ability to have Employees work in multiple states. Add ability to have Employees work in multiple localities. Add ability to enter Work Types, and to have Employees who use multiple Work Types. After this will be the log itself. There will be a main heading for each object, which includes the object type, number and name. This heading will also include the Version Tag of the object before it was changed, or if it is a new object, the words "New Object". The various object headings should be entered in order, so that they are easy to find. Following the object heading will be the log entries. The easiest way to create these log entries is to copy the information that you wrote into the Documentation Trigger of the object and indent it. This way, you will have the Reference Number, the programmer, the date, and a short description of the modification (you can erase the project name and the Solution Center name if you wish). Here is an example: Table 10077 - Time Journal Line - NS012 NJD01 - Navision, John Doe, 02/12/00 Added the new State and Locality fields. Modified the trigger code to default these fields whenever the Employee No. is entered. Here is an example of a new object: Table 10082 - Split Information - New Object NJD01 - Navision, John Doe, 02/12/00 New table which links a Split Control with the various Substitute Controls for a single Employee or for a standard split (indicated by a blank Employee No).

Change Log A Change Log details all of the changes you made for a Project. It tells another developer, without any ambiguity, every single change that must be made to go from one version of the product to another. You must create a Change Log so that other developers can see exactly what was done to the objects. Even more important, you must have these Change Logs available when it comes time to upgrade your customizations to a new release of the Navision product.

Development Methodology

4-37

There are three recommended methods of creating a Change Log. All three use plain text files for a simple reason - by using plain text files, it is easy to copy changes from the Change Log and paste them directly into a Navision Object.

Manual Change Log The best method for creating a Change Log is to create it manually. Using a manual change log, you can describe exactly how to make the changes using C/SIDE, plus for code changes you can copy and paste entries into C/SIDE, rather than using the text format. Naturally, the big disadvantage to a manual change log is the time that it takes to create one. Therefore, we only use it in house for Attain Improvements, where we know that they will be used many times. And for Solution Centers, we only recommend a manual change log if you are making an Add-On product, again, where it will be used many times. To help you with this, on your class disk there is a file called TEMPLATE.LOG, which contains the various instructions and templates that we use to make manual change logs here.

Automatic Change Logs We also provide two methods of making Automatic Change Logs. They both work using the text files that you can export from C/SIDE. They basically compare the text lines and print a report showing the differences between them. Both of these methods were developed using C/SIDE. The advantages of an automatic change log are the speed and ease of creating them, and the completeness of the results (as long as you know which objects were changed). The disadvantage is the long time it takes to actually use them and the difficulty in understanding them. For example, if you insert a single field into a tabular window, it will generate many pages of changes, since each column had to be moved to make room for a new field. Once you are used to using these change logs, and you can easily read the exported text objects from Navision, this disadvantage decreases. One of the two Automatic Change Logs is the Compare Tool. We have included the Compare Tool on your class disk, along with documentation explaining how to use it. It makes it easier to understand Change Log than the alternative. The Compare Tool is recommended whenever you are publishing a Change Log, for example if you are including it with an Add-On. The alternative method is the Merge Tool. This will be covered later in this

4-38

Navision Attain Solution Development

course. Although its change logs are more difficult to read, the advantage of using this method is its integration with the merging capabilities. If the main reason for the Change Log is its help when installing upgrades, then this method is the best.

Chapter 5 Posting Routines

In this section we will be discussing the way that Journal lines become Ledger entries. First well discuss Journals and Ledgers. Then well jump right into the codeunits. The last thing to cover in this section is how documents are posted to ledgers. Stay focused. If you ever intend on changing posting routines, it is crucial that you understand these basics. There are many more things about posting routines that we do not have the time to get into, but this is a good place to start. This chapter covers the following sections: 5.1 Whats the Difference between a Journal and a Ledger? 5.2 Standard Journal to Ledger Posting Routines 5.3 The Main Three Codeunits 5.4 The Theory behind Document Posting 5.5 The Codeunits Used in Document Posting

5-2

Navision Attain Solution Development

5.1 Whats the Difference between a Journal and a Ledger?


In this section, you will learn the major differences between a journal table and a ledger table and how they are used in the functional area. You will also learn how dimensions are associated with these tables.

Journal A Journal is a temporary work area for the user. Records can be inserted, modified and deleted at the users whim. There are actually three tables that are used to make up the Journal: The main table is the Journal Line table. There are two supplemental tables called Journal Template and Journal Batch. These tables are used primarily as filters on the Journal Line table.

The Primary Key of the Journal Line table is a compound key (has more than one field). It consists of Journal Template Name, Journal Batch Name and Line No. The journal form that the user chooses, sets the Template Name and this does not change unless the user goes into a different journal form. The Batch Name may be changed at the top of the form (the options that are available depend upon the Template chosen), but only one can be viewed at a time. The line number keeps each record in the same template and batch unique. Line number is incremented automatically by the form (see the AutoSplitKey property). The user never even sees most of the Primary key fields on the form (other than the Batch). The journal form lets the users enter journal lines that will be added to the detail tables of the system (the ledgers), but nothing happens until the user decides to Post. They can leave the lines in the journal table as long as they wish without posting.

Posting Routines

5-3

Ledger A ledger is a protected table that holds all the transactions for a particular functional area. These records are permanent and cannot be deleted or modified except through special objects. Records also cannot be inserted directly into the table. Records cannot get into a ledger except through a Posting Routine, and Posting Routines only post journal lines. The Primary Key is a simple one Entry No. which is an integer. Entry numbers start at 1 and have a maximum of 2,147,483,647. Dont worry, if the company posts 100,000 entries a day, 365 days a year, it would still take about 60 years to run out of numbers. There are also many Secondary Keys and most are compound. They are set up for reports, forms and FlowFields. The Ledger table holds the majority of detail information for the functional area and so it is very important to all other objects. Note A Ledger table should never be modified directly, especially inserting or deleting records. There is a linkage between most of the ledger tables back to the General Ledger. Because of this linkage, any modifications made directly to the table can be disastrous. Usually the only way to undo the changes made in this manner, is to restore the most recent backup of the database.

Dimensions As you may know, each journal line can now have an unlimited number of dimensions associated with it. These dimensions are transferred along with the journal line to the ledger tables. From most journal forms the user can click the Line button to add dimensions to the journal line. They are stored in a table called Journal Line Dimension. This table is subsidiary to the Journal Line table. When the line is posted to the ledger, those dimensions are copied to the Ledger Entry Dimension table. From most ledger entries forms, the user can click the Entry button to view the dimensions for that ledger entry record. The Ledger Entry Dimension table is subsidiary to the ledger entry tables.

5-4

Navision Attain Solution Development

5.2 Standard Journal to Ledger Posting Routines


Whats the Job of a Posting Routine? A posting routine is a group of codeunits that is responsible for making sure that all transactions that are put into the corresponding ledgers are correct per line and correct as a whole. The posting routine takes Journal Lines, checks them, converts them to ledger entries, inserts them into the ledger table and assures that all transactions made were consistent.

The Standard Codeunits in Journal Posting Routines The primary codeunit that does the work of posting for a particular journal is simply called the Posting routine. This codeunit is named after the Journal name with the addition of "-Post Line". Its main job is to transfer the information from the Journal record to the Ledger table, though it also does other things, such as calculations and data checking.

Posting Routine Companion Codeunits


The posting routine Codeunit has two companion Codeunits - one named "Check Line" and the other named "-Post Batch". The Check Line routine is called by the Post Line routine to check each Journal line before bothering the server with it. Thus, all of its testing routines either do not touch the server at all, or at most only once per posting process. The Post Batch routine repeatedly calls the Check Line routine to test all lines and then repeatedly calls the Post Line routine to post all lines. The Post Batch routine is the only one that actually reads or updates the Journal table; the others simply use the Journal record passed into them. This way a programmer can call the Post Line routine directly (from another posting routine) without having to update the Journal table. The Post Batch routine is used only when the user selects Post within the Journal form.

Standardized Object Numbers The last digits of the Object Numbers of these Posting routines are standardized: The Check Line always ends with 1, the Post Line with 2 and the Post Batch with 3.

Posting Routines

5-5

As an example, Gen. Jnl.-Check Line is Codeunit 11, Gen. Jnl.-Post Line is Codeunit 12, and Gen.Jnl.-Post Batch is 13. Note that none of these routines have any interface that requires user input. This is so that they can be called from other applications without having to worry about messages popping up (except error messages). The Post Batch routine has a dialog that displays the progress of the posting and lets the user cancel. The rest of the user interface having to do with posting, is handled by another set of routines: The Post routine (which just asks if you want to post and then calls Post Batch) ends with a 1. The Post and Print routine (which asks if you want to post, calls Post Batch and then calls the Register Report) ends with 2. The Batch Post (which asks if you want to post the selected batches and then repeatedly calls Post Batch for each one) is called from the Journal Batches form and ends with a 3. The Batch Post and Print (which asks and then for each batch calls Post Batch and then calls the Register Report) ends with a 4. As an example, Gen. Jnl.-Post is Codeunit 231, Gen. Jnl.-Post+Print is Codeunit 232, Gen. Jnl.-B.Post is Codeunit 233, and Gen. Jnl.-B.Post+Print is Codeunit 234.

5-6

Navision Attain Solution Development

5.3 The Main Three Codeunits


Our focus in this section is on the worker bees of posting routines: Post Batch Post Line Check Line

These three codeunits have the job of taking a batch of journal lines, checking them, and putting them into the corresponding ledger table. Each codeunit has a set of responsibilities and together the codeunits do the job of making the journal entries permanent. On the next few pages, we will be discussing the responsibilities and parts of all three of these codeunits. To aid in the discussion, we will be looking at an example the Resource Journal Posting Routines. The three Resource Journal Posting routines are
1

Res. Jnl.-Post Batch (codeunit 213) Res. Jnl.-Post Line (codeunit 212) Res. Jnl.-Check Line (codeunit 211) Open Navision Attain and select the Cronus Company to get ready for the next few pages.

Check Line The name of this codeunit explains its function. It is designed to check the Journal Line that is passed to it. It does so without reading from the server except perhaps the first time it is called.
2

Go to the object designer and design codeunit 211. Look in the RunCheck function for any server calls (GET, FIND, INSERT, MODIFY, DELETE, and so on.). Try to see if they are being called every time or just once (as they should be).

You may notice that the code in the OnRun trigger of this codeunit is inserting records. The OnRun trigger of CheckLine is normally never called, but in prior versions of the product it was. For backward compatibility, the OnRun trigger loads the temporary dimensions table with the two global dimensions and then

Posting Routines

5-7

calls the RunCheck function. This is the function that does all of the real checking. Take a look at this function in codeunit 211. Before checking any of the fields, this codeunit usually makes sure the journal line is not empty. It does so by calling the EmptyLine function in the Journal table. If the line is empty, it is skipped by exiting immediately from the codeunit. There is no error, and the posting process will continue.
3

Notice the EmptyLine function call. Go to the object designer and design table Res. Jnl. Line. Find the EmptyLine function and see what it actually returns.

The codeunit uses functions like TESTFIELD, NORMALDATE, and others to check the value of fields. It checks only one Journal Line at a time. If a value is not filled in that should be, or contains an incorrect value, the codeunit uses a FIELDERROR to report the problem to the user (the ERROR function is not used here because it does not provide the user with enough information to find the problem). FIELDERROR tells the user the record that caused the problem and which field had the error.
4

Go to the object designer and design codeunit 211. Look for any error commands (ERROR, FIELDERROR). Which one is used most often?

The last thing that RunCheck will verify is the validity of the dimensions that are passed into the function in the temporary dimensions table. This is done by some simple calls to the Dimension Management codunit. If the codeunit does not stop the process with an error, then the journal line is accepted for now.

Post Line This codeunit is responsible for actually writing the journal line to the ledger. It only posts one Journal Line at a time. It does not look at previous or upcoming records.
5

Go to the object designer and design codeunit 212. Look in the Code function for any movement commands for the actual journal line (GET, FIND, NEXT). Are there any for the journal line? How is the record read from the database?

You may notice that the code in the OnRun trigger of this codeunit is inserting records. The OnRun trigger of PostLine is normally never called, but in prior versions of the product it was. For backward compatibility, the OnRun trigger

5-8

Navision Attain Solution Development

loads the temporary dimensions table with the two global dimensions and then calls the RunWithCheck function. This is the function that is normally called by other functions or triggers. It in turn calls the workhorse of the PostLine routine, the Code function.Take a look at the Code function in codeunit 212. Like Check Line, this codeunit skips any empty lines by exiting. This assures that empty lines are not inserted into the ledger. The first thing the codeunit does if the line is not empty is call Check Line to verify that all the needed journal fields are correct.
6

Notice the EmptyLine function call. This is the same function we have already looked at.

The second thing it does (only when called for the first time), is Lock the Ledger table. This prevents anyone else from posting while this posting is being done. This locktable starts the posting transaction. It also finds the last entry number that is currently in the ledger the first time through, and stores that value in a variable. Subsequent calls to this codeunit will not lock the table or read it for that matter.
7

Notice the line IF NextEntryNo = 0 THEN BEGIN. This block of code is found in almost all Post Line codeunits. Look at the code and figure out whats going on. Remember that this block of code is only executed once.

Next, the important table relations are checked. This requires reading the database (using GET), therefore it is done here rather that in Check Line.
8

Notice the GET statements found in this codeunit. What types of records are we getting? Why do we use a GET here?

Before writing to the ledger, the codeunit first writes to the register. It inserts a new record the first time through and all subsequent calls modify the record with the new To Entry No..
9

Look at the code that writes to the Register. What information is stored there?

Then the codeunit takes the next entry number and the values from the journal line and puts them into a ledger record. It can finally insert the ledger record.
10

Find the assignments from the journal record to the ledger record. Just below that, there are some recalculations that must be done before we store the ledger record. Why do you think these are here?

Near the bottom of the Code function is the call to the Dimension Management

Posting Routines

5-9

codeunit that copies the dimensions from the temporary journal line dimension table to the real ledger entry dimension table. The entry number for this new ledger record is passed into the function to keep the dimension records associated with this ledger entry. The very last thing that the codeunit does is to increment the variable that holds the next entry number by one. Thus, when the codeunit is called the next time, the next entry number is ready. When post line is done one journal line has been processed, but more than one ledger record may have been inserted into more than one ledger.
11

In the resource journal post line codeunit, only one ledger record is created, but in the general journal post line codeunit, a much more complicated set of rules are in effect because there are four ledgers and not just one. The basic structure of the codeunit, however, is still the same.

Post Batch This codeunit is responsible for posting the Template and Batch that were passed to it.
12

In the resource journal post batch codeunit, there is a lot of code that deals with the Template and Batch parts of the journal lines. The important thing to remember is that this codeunit only posts one Batch at a time. Can you find the lines of code that assure this?

Of course, only one record variable for the journal was actually passed in, but the codeunit starts by filtering down to the template and batch of the record that was passed in. Then it finds out how many records are in the record set that the record variable represents. If the answer is none, the codeunit exits without error and it is up to the calling routine to let the user know that there was nothing to post.
13

Find the line of code that checks for the existence of records in the Batch. How does it work?

It can then begin checking each journal line in the record set by calling Check Line repeatedly for each one. Once all the lines are checked, they can be posted by calling Post Line repeatedly for every one of them. By now the codeunit has looped through all the records twice, once for Check Line and a second time for Post Line. To call the appropriate functions in Check Line and Post Line, Post Batch must fill in a temporary journal line dimension table with all of the dimensions for the journal line. Then it can pass this temporary record variable into the RunCheck function of Check Line (or the RunWithCheck function of Post

5-10

Navision Attain Solution Development

Line) along with the journal line record variable.


14

Look for the calls to Checkline and Postline. There are codeunit variables in the Global Variables window that have these codeunits defined. How are the codeunits called? What is passed to the codeunits?

This codeunit may also be responsible for making sure the journal lines balance. This usually takes place after they are checked and before they are posted.
15

Resource journal lines do not have to balance, but general journal lines do.

It may do other special things depending on the Journal Template. For recurring journals, the journal lines are updated with new dates based on the date formula. When a recurring journal line is posted, this codeunit must check the description and document number fields and perhaps replace any replaceable parameters with the correct values (%1 = day, %2 = week, %3 = month, and so on.).
16

Find some places in the code where it checks to see if this is a recurring journal. How does it know if it is or is not?

If the template is not recurring the codeunit deletes all the journal lines.
17

Locate the DELETEALL statement. Notice that there is no loop that deletes all the records.

Finally, once every journal line is Posted and/or deleted (or updated), the codeunit calls COMMIT. This ends the posting transaction that was started by Post Lines locktable.
18

Finally, find the COMMIT at the end of Post Batch (the end of the OnRun Trigger). Why do we do a commit here?

Posting Routines

5-11

5.4 The Theory behind Document Posting


Now that you understand how one journal line becomes one ledger entry, we can talk about how one document can create dozens of ledger entries.

What is a Document? As we have already discussed, a Document is an easy interface for a user to make many complicated transactions. In this section, we will look at the major parts of the Sales Posting codeunit that posts all sales documents.

Breaking it Down In a Sales document, the user is trying to tie a customer to a series of transactions. Each individual transaction could be performed by several journal entries into the correct journals, however, the user needs to total all of the transactions in order to easily bill the customer and make the process of taking the order much easier as well. A data entry person is capable of taking an order over the phone and creating the document. The user could then tell the customer over the phone the expected price of the entire order. This is the goal. So, now we have an order. But Navision is not built around the concept of an order. We need to take the information that was gathered by the user and translate that into the correct journal entries. A Sales document could be as complicated as the following diagram

5-12

Navision Attain Solution Development

The diagram shows the posting of a Sales Invoice that has three sales lines: On Line 1, we are selling a G/L Account (perhaps this line adds some kind of surcharge or freight). On Line 2, we are selling an Item (say a computer). On Line 3, we are selling a resource (here we are talking about time that one of our employees has spent custom building the computer).

Note that the Invoice as a whole (header and lines) generates a journal entry that will debit the Accounts Receivable Account in the G/L. The corresponding Credits come from the individual lines. Each line could generate a separate G/L entry for the amount of that line. Note that if the lines use the same General Posting Setup record, department, project and so on, they may actually post as one G/L Entry. At the same time that all of these entries are being posted through the General Journal, there are entries being made to the Customer, Item, and Resource Ledgers. The entry to the Customer Ledger is made by the original General Journal entry. The entries to the Item and Resource ledgers are made via Journal entries to the Item and Resource Journals respectively. There are many journal entries that are automatically made by the Sales Post routine on behalf of the user. When these journal entries are posted, they are posted as if the user had put them into the journals themselves. The biggest difference is that the journal records are posted one at a time, which allows the Sales Post routine to bypass Post Batch and call Post Line directly. In the example, codeunit 12 Gen. Jnl.-Post Line would be called at least twice, codeunit 22 Item Jnl.-Post Line would be called once, and codeunit 212 Res. Jnl.Post Line would be called once.

Posting Routines

5-13

5.5 The Codeunits Used in Document Posting


A sales document is posted primary by codeunit 80 Sales-Post. You can however post an entire batch of sales documents by calling report 297 Batch Post Sales Invoices. Note that this report only does invoices. There is a separate report for each document type. These reports call codeunit 80 repeatedly for each document. For this to work, codeunit 80 must not interact with the user. In fact, codeunit 80 is never called directly by a form. The form calls codeunit 81 Sales-Post (Yes/No) or 82 Sales-Post + Print or one of the reports mentioned above. They in turn interact with the user (getting confirmation or other information) and then call codeunit 80 appropriately.

Focusing in on Codeunit 80 (Sales-Post) If we focus in on codeunit 80, we can break it down into some of its major parts. We will assume the user is shipping and invoicing a Sales Order. Determine what the posted document numbers are going to be and update the Header. This section ends with a COMMIT. Insert the Shipment Header and Invoice or Credit Memo Header. Process the Sales Lines. This section starts by clearing the Posting Buffer (a temporary table with a special primary key) and ends with the UNTIL that goes with REPEAT that loops through all the Sales Lines. Inside this section, each line is processed one at a time. The line is checked. The line is checked with its matching Shipment line (if the line was previously shipped). If the line type is an Item or a Resource, it is posted through the correct Journal. The line is then added to the Posting buffer. It may be inserted or it may update a row already there. If the line is related to a Job, then it posts a Journal line through the Job

5-14

Navision Attain Solution Development

Journal. Then if there is no shipment line, it inserts one. Finally it copies the Sales Line to the Invoice Line or Credit Memo Line (the posted tables). Now, it can post to the G/L, all the entries in the Posting Buffer. These are the Credits that are created from the Sale of the lines. Then it can post the Debit to the G/L. The customer entry is made to the Sales Receivables Account. It checks to see if there is a balancing account for the Header. This corresponds to an automatic payment for the invoice. Lastly, it updates and/or deletes the Sales Header and Lines and commits all changes.

Chapter 6 Data Conversion

Almost always, when a Navision Solution Center (NSC) gets a new customer, that customer has already been using a computerized accounting system. As a result, one of the many projects needed for the new customer, will be a data conversion project. In this section, we will cover how to complete a data conversion project and how to use one of the many tools used for data conversion, the Navision Attain Dataport Object. This chapter covers the following sections: 6.1 Transaction Imports 6.2 Importing Documents 6.3 File Handling in Navision Attain

6-2

Navision Attain Solution Development

6.1 Transaction Imports


Normally, for a Master or Supplemental table, the only code you will need, is to fill in data that is required for Navision but missing from the import. Occasionally, you will need to generate the primary key (say, Customer Numbers) during the import as well. More often, though, you will need nothing. When we get to transaction imports, such as bringing in open invoices or beginning balances, you will always need trigger code, because whenever transactions are brought into Navision, you must always check them to see if they follow the Navision Business Rules. If bad data is brought into Navision Attain, it will cause you and your customer to spend hours or days fixing data up that could have been handled automatically during import. One other important note - Under no circumstances, will you ever import directly into a Ledger Table! Not only would there be no Business Rules you could test against (since all posted transactions are assumed correct), but there would be no way for your customer to fix the inevitable corruption. In fact, the only sure method we have found for fixing this sort of disaster is to erase all Registers and all Ledgers and start over.

Do Not Import into Ledgers! What should you do instead? Import into the corresponding Journal. When you import into a Journal, you will have two key choices as to what to do with the records. First, you can store the Journal records into a Journal. This has the advantage of allowing the customer to review the entries and possibly make modifications before they are actually posted. The disadvantage is that it takes more work to program this and more time for the actual data conversion. Second, you could post the Journal Entries as they are being imported. This has the advantage of being a one-step conversion process, faster and easier to understand. The disadvantage is that the information must be correct, because any errors will become permanent. With proper testing, this should not happen, but sometimes the customers data is such that you cannot count on it being correct.

Data Conversion

6-3

Should You Save the Journal Lines or Post Them? Consider the following factors when you make your decision:
1

Will the customer really have time to manually review the imported data during the data conversion?

For most data conversions, the testing phase is over before the data conversion begins. The users will go home on Friday after using the old system for the last time, and come in on Monday using Navision Attain. In this situation, it is far better to post the entries as you import them, and test thoroughly before that day. However, sometimes a customer will want to run parallel for a while, or does not mind that some data will not be converted yet when they switch to Navision Attain. This is especially true for historical information like old invoices and the payments that closed them. In this situation, it might be desirable to import into the Journal and store the records there.
2

What is the status of the customer's existing data?

If the data is missing a lot of information needed by Navision Attain, if it is corrupted, or in some other way not reliable, you will be forced to import and store the information into the Journal. This will allow the customer to fill in the missing data and fix the inaccurate data before posting. However, if the customer's data is in good shape, this should not be necessary.
3

Finally, what is the status of the testing?

If the data conversion date is looming near and the testing of the data conversion has not been thorough, you may be forced to fill in the Journal and store the information there rather than post directly. You should not take any chances on bad data getting into Navision Attain and, without thorough testing, you will never know. Should this situation occur, try to get the conversion date delayed. If you cannot, do not post during the import. Keep in mind that this decision can be made independently for each transaction data type you are importing. For example, you could decide to import open invoices and post directly so that

6-4

Navision Attain Solution Development

the Customer Ledger will be up to date upon conversion. However, you could decide that the closed invoices and the payments that closed them could be imported and stored into the journal, so that the customer can review the results before posting. After all, they do not need this old information to run their system.

What Code in What Trigger? Why do you need code when importing transactions? To make sure that the Business Rules for the application are being followed. To initialize records so that data is not accidentally transferred from one record to the next. To fill in missing information the record must either be stored or posted.

The following are the main triggers that will be used for these purposes: OnPreDataport Validate any options the user may have entered on the Request Form. OnPreDataItem Insert code that will be run once for the entire Dataport. If you are inserting the records into the Journal, this is where you will determine what the first line number will be. OnBeforeImportRecord Insert code that will initialize the record to be imported. At the least, put in an INIT function call. OnAfterImportRecord Here is where most of the work will be done.

You will need to validate the information being imported, fill in missing information and finally store the record in the Journal or post it.

Calling Journal Validation Routines As you recall, most of the Business Rules are contained within the table triggers of the Journal table. Therefore, most of the processing that you will be doing will involve calling the Journal Validation routines (the Journal fields OnValidate triggers).

Data Conversion

6-5

Which ones should you call? Well that depends on what kind of data is being imported. You need to call the validation routines whenever there is a Table Relation that must be tested. You also need to call them whenever the entry of one field affects what goes into the other fields.

Use the Debugger


The best way to be sure the proper routines are called, is to go into the journal, insert a new line, clear any fields that contain default values (dataports dont default things for you), turn on the debugger and start making the entry. Do not do any lookups (i.e. do not press F6). Skip any fields that are not in your customer's data. Watch what happens as you enter each field. On any field where the debugger does not come up, there is no validation code for that field, and unless it has a Table Relation, you can safely skip it. If a trigger comes up which is not a validation trigger (it does not start with OnValidate), then ignore that trigger and press F5. If the debugger does come up on a trigger which starts with OnValidate, it means that it is probably worthwhile to call the validation code. Write down that field. Then, press F5 (Run) and see if another field validation code (OnValidate) comes up. If so, write down that field indented under the first. Continue to do this until you are back on the journal entry form. Then, look on the Journal entry form and note any fields that have changed value since you entered the field. This is data that is filled in automatically as part of the validation process. Once you have entered all the fields that are in your customer's data in this manner, turn off the debugger. If this is a General Journal Line form, enter another line to balance your entry. Now, try to post. Do you get any errors? Normally, this will be the result of missing or invalid data. Write down the problem; fix it manually, then post again. Continue until you have found all of the problems, and the line posts correctly. Now, you can go into your dataport and add calls to the validation routines. The function you will use is the VALIDATE function. For example, if you needed to Validate the Account No. field, you would use: VALIDATE("Account No."); Remember that you should do this in two cases:
1

First, if during your debugging, the debugger came up when you entered the field, this indicates that there is validation code to be called.

6-6

Navision Attain Solution Development

Second, if the field has a Table Relation with another table, the VALIDATION routine will also test the Table Relation.

If validation code came up from another field when you validate a field (an indented field on your list), you do not need to call the validation code separately for that field. However, this can affect the order in which you call validation routines. For example, if you validate the Posting Date in the General Journal, the validation code for the Payment Terms Code is also called. Later on, when you enter the Payment Terms Code, it is validated again. In this case, you should first fill in both fields, then call the validation routine for the Posting Date only. You will not need to validate the Payment Terms Code separately, since the Posting Date validation calls it for you.

Activity Debugging the General Journal In this scenario, you need to import beginning balances into the General Ledger. The customer's system will export this information in variable length field (comma separated values) format. They have told you that this is the balance as of June 30, 1999. The information exported for each line is: The G/L Account Number The Transaction Description The Amount (positive = debit, negative = credit)

Go into the General Journal and, using the procedures outlined in the previous section, determine which fields need to be validated and which additional information is needed to post this entry correctly. Here is some test data you should use: Account No. = 11200 Description = Beginning Balance as of 6/30/99 Amount = 7324.12

Which of these fields need to be validated?

Data Conversion

6-7

Which fields are missing and must be filled in before you can post?

What other things did you notice that might affect the import?

Transaction Imports (continued) One thing you probably should have noticed is that when the Account No. is validated, the Description field is filled in automatically. If this field had been imported and then the Account No. validated, then the imported value would have been lost. How are you going to get all the data you need to import? Rather than importing directly into a field, you will often need to import into a variable and then transfer the contents of that variable into the right field at the right time. To import into a variable, create a global variable and put that variable's identifier into the SourceExpr property of the Dataport Field rather than the actual field name. Then, in your OnAfterImportRecord trigger, after you call the validation code for the Account No., transfer the Description from the variable to the field. When you import any transactions, there is another field, which, even though you do not strictly have to fill in, you should fill in every time. This is the "Source Code" field. This field follows a transaction wherever it goes and tells

6-8

Navision Attain Solution Development

where it came from. You should create a Source Code for each Import routine and set the Source Code for every entry that goes through that routine to that Source Code.

Activity Creating a Transaction Dataport This is a continuation of the previous activity. On your class disk, you will find a file called BEGBAL.CSV. This file contains Journal Entries in the same format as described before. We will not be using dimensions for posting at this time. Our customers and salespersons are however set up for dimensions. Go to table 352 and delete the dimensions for customers and salespersons. Also, our GL Accounts are not set up for direct posting. Create a processing only report that will check on direct posting for posting accounts only. "G/L Account"."Direct Posting" := TRUE; "G/L Account".MODIFY; Write a Dataport to import this file. Fill in all the triggers to initialize the record, validate the fields necessary, and fill in the missing fields. We are not ready to do anything with the record yet. Therefore, temporarily, at the end of the OnAfterImportRecord trigger enter the following line of code: CurrDataport.SKIP; This will prevent the dataport from doing anything to the record, like storing it in the journal. Then you can test your code without causing any harm. Save this Dataport object as number 91101.

Saving Journal Records As you remember, one of the options for importing transactions is to store the Journal record. To do this, you must remember how the primary key for a Navision Journal table is created. It contains three fields: The Journal Template Name

Data Conversion

6-9

The Journal Batch Name The Line No.

None of these values will be in any export that you get from the customer. Therefore, you must set these values yourself. The Journal Template and Batch will pinpoint in which journal the user will find the entries when the import is complete. The easiest way to handle this is to create a batch for import purposes in whichever journal you are using, and then in your dataport, set the Template and Batch names to the ones that you selected and created. As a test at run time, to make sure that the journal batch actually exists for use by the customer, you might want to do a GET on the Template table and the Batch table using the values you are setting. The Line Number will actually be on the line in the journal where the user will find the data. This must be different for each import line. To do this, you should find the highest existing line in the journal batch and add 10000 to it for the first line you import. Each succeeding line should be 10000 beyond that. Why 10000? As you recall from looking at the AutoSplitKey property used by all Journals, these are the numbers that the AutoSplitKey property would have chosen had the user inserted these lines itself. Here is an example of a piece of code that will find the highest existing line in a journal batch (if any), and add 10000 to it: LOCKTABLE; SETRANGE("Journal Template Name",'GENERAL'); SETRANGE("Journal Batch Name",'IMPORT'); IF FIND('+') THEN NextLineNo := "Line No." + 10000 ELSE NextLineNo := 10000; The LOCKTABLE is used to make sure that we have the latest version of the Journal table before we start, and to make sure that nobody else tries to update the Journal table at the same time we do. The SETRANGE functions set filters on two of the three primary key fields. The FIND searches for the last record, but note that it is within an IF statement, so that in case there are no current records in the batch (the normal case), the code will handle it by starting at 10000. The other thing you must do when importing transactions is to modify some of the DataItem properties to remove some of the unwanted automatic processing.

6-10

Navision Attain Solution Development

For importing journals, you should set the AutoSave property to Yes, and the AutoUpdate and AutoReplace properties to No.

Activity Saving the Journal Records Part 2 Now, modify your import routine (Dataport 91101) to save the Journal Records, as described above. Don't forget to remove the CurrDataport.SKIP function, so that this time the records will be saved. Test your Dataport using the BEGBAL.CSV file on your class disk. Now, go into the journal and see what your entries look like. Did you remember to create the batch before you imported? If not, go ahead and create it now - the entries are already there.

If there are any obvious problems, modify your dataport to fix the problems and import again. Do you now have two copies of the import in the same journal? Good! This is how the dataport was designed to work. Now, go back and delete the entire contents of the journal and try again.

Now, try to post the entries. Any problems? Again, go back and fix your dataport so that all problems are resolved. By the time you are done, you ought to be able to post the imported file. One of the problems you can have is that it can insist on a particular document number. If this happens, you can be tempted to set the Document No. to this value. Don't! Instead, go into your Journal Batch setup and remove the value in the "No. Series" field.

Posting Journal Records The second option for importing transactions is to simply load the journal record, but rather than saving it, posting it directly. For this there are only a couple of things you must do. You do not need to worry about any of the primary key fields any more, since you are never going to store the record. Instead, all you need to do is call the posting routine. To find the correct posting

Data Conversion

6-11

routine, refer to the material on your class disk in the Architecture section. You just need to look for the Journal Post Line routine. Create a codeunit type variable for the posting routine. Then, at the end of your OnAfterImportRecord trigger, after you have set all the fields up properly, call the codeunit's RUN method, using the journal record as the parameter. An example: GenJnlPostLine.RUN("Gen. Journal Line"); Much easier than saving the record? Oh, one other thing you must do - Go into the DataItem Properties and set the AutoSave property to No, along with the AutoUpdate and AutoReplace. Remember that you are no longer saving these journal records anywhere.

Activity Posting the Journal Lines Part 3 Now, go back into your Dataport object. Save it as another object number, so you can keep all the work you did before. Now, modify your Dataport to remove the code and variables that you needed simply to store the journal line. Instead, add the code needed to post the journal line directly. Don't forget to set the AutoSave property to No. Now test your import. Since you already tested it when posting, you should have no troubles now. If you do, go over your work carefully and see where the problem might be and fix it.

6-12

Navision Attain Solution Development

6.2 Importing Documents


Importing Documents is a more complex task than importing journal entries. There are many more fields to import and many more of them are needed before a document entry is complete. In fact, there is sometimes so much data that it runs into the limits of the Dataport (600 to 650 characters per line). Worst of all, there are two different types of records to be imported, header data and line data. As you have seen, it would be difficult to import two different types of data using a Dataport. For these reasons, we do not generally recommend importing documents. For historical data, importing the historical transactions through the journals is usually sufficient. For open Sales Orders or open Purchase Orders, we recommend that the customer enter them by hand right after the data conversion. This usually makes a fairly good training and confidence building exercise. However, in some situations, depending on the business, the customer may want to import open orders. For example, if there is a long lead-time between order and shipment, you can have open orders going back several months. Also, some customers would like to see historical documents. For example, the summary information for invoices are brought in through the journals, but the customer may want to see the line by line detail that only exists on the original invoice document. If the customer wants this, and is willing to pay for it, the best method would be for the customer to split the information into two files - one holding the header information and one holding the line information. If this is done, you can probably use a Dataport to import. If not, you will need to use another, more complex method outlined as follows.

For Open Orders For Open Orders, you will have to validate fields for both the header and the line. If the customer has partially shipped orders, only bring in the portion that is still open. It is far too complex to try to simulate a partially shipped order in Navision without actually shipping it through Navision Attain. When you bring in the lines, you will have to use a similar set of code that you did with journals. First, you set a filter on the Document Type and the Document

Data Conversion

6-13

No. fields. Then, you find the existing line with the highest number, and add 10,000 to that for the Line No. of the line you are importing.

For Historical Documents For Historical Documents, the processing is simpler. For one thing, since you already brought in the transactions (summary information), these documents are for viewing only. Therefore, there is no need to validate the fields. When bringing in the lines, you only need to filter by the Document No., since the table you are importing into implies the type. Also, you can enter the line numbers sequentially (1 higher than the previous highest number), since the user cannot insert. One thing to note, however, is that the historical tables are protected. You will have to give your Dataport permission to insert into these tables. Note that there is never a reason to bring in a document and then post it. Historical documents are already posted, while open orders have not been posted yet in your customer's existing system or in Navision Attain.

6-14

Navision Attain Solution Development

6.3 File Handling in Navision Attain


Dataports are not the only method to get data into Navision Attain. Through File Variables, you can import data from or export data to any file accessible through your operating system. We only have time to go through a few basics now, but we have also given you an import skeleton you can use in the future. The skeleton will work for any fixed field or comma separated value text files, as long as each line (no per-line limit) ends with a Carriage Return - Line Feed combination, as most text files do. This is on your Class Disk, in the Examples directory for this section, and the file is SkeletonFileImport.fob. It contains a single codeunit that contains functions that can be called from any Navision Attain object.

The File Data Type In order to gain access to an external file from within C/SIDE, you must first declare a variable of type File. This is a complex data type, which has numerous methods (functions) used to open, read, write and close external files. You would declare one File variable for each file you wish to access at the same time. You would, of course, be able to use one File variable to handle multiple files, but you would have to access them one at a time, since each File variable can be open to only one file at a time.

Opening Files for Import or Export When you are ready to use a file, you must open it first. Even before you open it, you must set it up properly. To set it up properly, you should determine first whether you are going to use it for reading (import) or for writing (export). Although you could theoretically open a file for writing and then read it as well, this is normally not done in Navision Attain. Here are the File Methods used to prepare a file for opening and for actually opening (and closing) it. As with other methods, these are called through the File variable. For example, if the File variable is named "ImportFile", then to use the Open method, you would enter: ImportFile.OPEN(Name);

Data Conversion

6-15

We will skip the "ImportFile." in front of each of these methods:

WRITEMODE(NewWriteMode) Sets the Read/Write status of a File variable before opening the file. If NewWriteMode is TRUE, you will be able to write to the file; if NewWriteMode is FALSE, then you will only be able to read from the file. Note that another way to use this method is like this: IsWriteMode := WRITEMODE;. By using this method after the file is open, you can tell whether a file is available for writing or not.

TEXTMODE(NewTextMode) Sets the type of data to be read or written. If TRUE, the file will be open in Text mode and if FALSE, it will be open in Binary mode. These will be explained a little later. This method can only be used before opening the file. Note that another way to use this method is like this: IsTextMode := TEXTMODE;. With this method, used only after the file is open, you can tell whether a file is being read or written in text mode or binary mode.

QUERYREPLACE(NewQueryReplace) Use this method if you are going to open a file using the CREATE method. If NewQueryReplace is TRUE, and the file already exists, C/SIDE will ask the user before a replace will be allowed. If NewQueryReplace is FALSE and the file already exists, C/SIDE will erase the old file and replace it with a new (empty) one, without asking the user. If the file does not already exist, this method has no effect.

OPEN(FileName) Use this method to open an already existing file. Be sure to set the WRITEMODE and the TEXTMODE before opening a file. FileName should be the full path name of the file. If you use OPEN as a statement (without looking at the return value) and the file indicated by FileName does not exist, a run-time error will occur. If you use OPEN as an expression (looking at the return value) and the file indicated by FileName does not exist, OPEN will return FALSE, but if the file does exist, it will be opened, and OPEN will return TRUE.

6-16

Navision Attain Solution Development

CREATE(FileName) Use this method to create and open a file. Be sure to set the WRITEMODE, the TEXTMODE and QUERYREPLACE before creating a file. FileName should be the full path name of the file. If you use CREATE as a statement (without looking at the return value), and the file indicated by FileName cannot be created (say the path does not exist), a run-time error will occur. If you use CREATE as an expression (looking at the return value) and the file indicated by FileName cannot be created, CREATE will return FALSE, but if the file is created, it will be opened, and CREATE will return TRUE. If the file already exists, it will be cleared and opened. Whether the user is warned about this or not depends on the parameter to the QUERYREPLACE method called before calling CREATE.

CLOSE Use this method to close access to the file through this file variable. Once this is called, you cannot use this file variable again to access a file unless it is reopened or re-created. If CLOSE is called and the file is not opened, a run-time error will occur.

Methods of Reading Files There are two methods provided for reading or writing data in external files. The method is set using the TEXTMODE method described before. There are two possible settings:

TEXT (TEXTMODE=TRUE) Each file access will read or write a line of text. The variable used can be of any type and it will be converted to (if writing) or from (if reading) text during the processing.

BINARY (TEXTMODE=FALSE) Each file access will read or write a single variable. The variable will be read or written in its internal format. For example, a Text is written out as a null terminated string whose length is the defined length of the Text variable. Since Text Mode is limited to one variable per line, note that you cannot have more than 250 characters per line in the file. Binary mode does not have this limitation, since it does not have lines. However, the internal format can really

Data Conversion

6-17

only be read if it was written in the same manner from Navision Attain. The one variable type that is very useful when using Binary mode is the Char type. Using this, you can read or write one byte at a time. In the SkeletonFileImport object, we use Binary Mode and the Char type to import text files that can be of any length.

Reading or Writing Data in External Files The following methods are used to read or write data in external files (once the file variable is open):

[Read :=] READ(variable) Read a variable from the file. The optional return value indicates the number of bytes read. If you are using Text mode, a line of text is read and the text is evaluated into the variable passed in as a parameter. If you are using Binary mode, the variable is read in its internal format, and thus the number of bytes read depends on the size of the variable.

WRITE(variable) Write a variable to the file. If you are using Text mode, the variable is formatted to text and written out as a line of text. If you are using Binary mode, the variable is written using its internal format. There are other File Handling methods that can also be used.

6-18

Navision Attain Solution Development

Which Method to Use? Generally speaking, for most purposes for which you would use the Text method to read or write data, you would be better off using a Dataport. The only exception would be to use the Text method to read or write variables of type Record. This will result in a tab-separated file, one line for each record, and each field separated from the others by a single tab character. This unusual format could be useful if you are transferring information from one Navision Attain database to another one. Other than this, and especially for data conversion purposes, if a dataport will not do what you want, then normally you will use the Binary method to read or write data in external files. When you have some time, study the Skeleton File Import object on your class disk to see how this can be done for an import.

Chapter 7 Coding in Forms

This Chapter explains the various form and control triggers, their functions and when they are fired. This chapter covers the following sections: 7.1 Form Triggers 7.2 Triggers for Rec 7.3 Control Triggers 7.4 Special Form and Control Functions

7-2

Navision Attain Solution Development

7.1 Form Triggers


In this section, you will learn about the form triggers that correspond to the users interactions with the Form itself. These triggers fire when something happens to the form.

OnInit This trigger fires as soon as the form object is created and before any controls are created. You cannot use this trigger to make controls visible or invisible because the controls do not exist yet. You can use this trigger to initialize global variables that the form will use.

OnOpenForm This trigger fires before the form is shown to the user, but after all controls have been created. You can use this trigger to make controls visible or invisible. You could also set additional filters on Rec (the forms record variable).

OnCloseForm This trigger fires right after the form is no longer visible to the user. You cannot stop the close of the form from this trigger. You might use this trigger to set the value of a variable that will be returned from this form.

OnQueryCloseForm This trigger fires as soon as the user tries to close the form but before the form is made invisible. If the trigger returns TRUE, the form will be closed. If the trigger returns FALSE, the form will not close. You can put code in this trigger to check the status of the form and then return the appropriate value to allow the form to close or stop the form from closing.

OnActivateForm This trigger fires whenever the form gains focus. If you attempt to use this trigger, you should know a couple of things about it. When the form is first opened, this trigger fires right before the form is visible. It is after the OnOpen trigger. This trigger fires every time the user returns to this form. So, it may fire many times depending on the activity of the user.

Coding in Forms

7-3

OnDeactivateForm This trigger fires whenever the form loses focus. When the form is closing, this trigger fires after the OnQueryCloseForm but before the OnCloseForm. Again, the user may cause this trigger to fires many times if they click back and forth between other forms and this form.

Activity Adding Messages to the Triggers In this activity, you will add messages to all of the triggers mentioned above to see exactly when they fire. Remember that messages will not appear to the user before the end of the process. It will appear as though several triggers fire at exactly the same time, but it is just the delay caused by the message function.
1 2

From the Object Designer, design form 21 (Customer Card). Add code similar to the following for each of the triggers mentioned in this section (use the actual name of the trigger in each message). Do not attempt to use the other triggers yet. MESSAGE('OnInitForm');

3 4

Close and save the form. Run the form. Which triggers fired (list them in order)?

Try bringing up the customer list form by pressing F5. Which triggers fired (list them in order)?

Close the form. Which triggers fired (list them in order)?

7-4

Navision Attain Solution Development

7.2 Triggers for Rec


In this section, you will learn about the forms built-in record variables and the triggers that are associated with them.

The Forms Record Variables Every bound form (those with a source table) has two built-in record variables. One is called Rec. The other is called xRec. You can use these record variables to access the current and previous records for the form respectively.

Rec Rec is the current record that the form is working with. Remember that it is just a record variable. Anything you can do to a normal record variable, can be done to Rec. You should be careful, however, when changing Rec in code. The form uses Rec to know which record it is on, and can get confused if you change to another record in certain triggers. If you need to change the underlying table of a form, you may want to consider using a global record variable that you create instead of Rec. This is usually easier. Of course, sometimes you want to change Rec. Perhaps, you need to filter Rec based on the users selection in a text box. Perhaps, you need to initialize Rec with values from another record variable whenever the user wants to insert. Perhaps, you want to remove filters from Rec or change the key. Whatever the reason, use care in deciding where to make these changes. You will find some helpful information in the description of the triggers in this section. The most common uses for Rec are to look at the fields and use their values. Rec is used to get the value that the user just entered, or the values of all the fields in the record. The fields in Rec are always exactly what the user sees on the form. If you want to see that values that Rec had before the user changed them, you would have to use xRec.

xRec xRec is the previous version of Rec. If the user has changed fields on the form but not moved off of the record yet, then xRec holds the previous values for all the fields. Like Rec, xRec is a normal record variable, but it should never be changed. It is updated by the form whenever a trigger fires, so any changes you might make would be lost. The only purpose of xRec is for comparison to Rec. In some cases, xRec is actually a different record altogether. If the user has just pressed F3, the value of Rec is an empty record, while the value of xRec is the

Coding in Forms

7-5

record the user was on before they pressed F3.

Automatic Actions Forms do a lot for the user and you. You need to be aware of what happens automatically for the user, while they are on the form. Records are automatically inserted on forms when the user finishes filling in the primary key fields for a new record (the new record is shown to the user when they press F3 or move past the last record). The only exception is when the primary key fields are not on the form or if the DelayedInsert property of the form is set to Yes. If DelayedInsert is set to yes the Insert will happen automatically when the user leaves the record. The primary key fields are not on the form and DelayedInsert is set to No, the automatic insert could happen at any time while the user is editing fields. Records are automatically modified on forms when the user changes fields in Rec and leaves the record. This could mean going to the next, previous, first, or last records. It could also mean the closing of the form or the pushing of a button. There is no way for the user to easily cancel the changing of several fields. When the user closes the form, the record will be modified. There is one way to cancel changes on a form. If the user decides that the changes made should not be saved and the record has not been saved, the user can press F4 to delete the record. When prompted to delete, if the user says no, the values that the user entered are lost (Rec is reset). This is not advisable, because if the user accidentally hit Yes, the entire record would be lost. Records are automatically renamed on a form when the user changes the primary key values of an existing record. The form prompts the user to confirm the change. If the user clicks Yes, the record is renamed. If the user clicks No, the record is left exactly as it is and focus is put back into the control that the user tried to leave. The user must then hit escape to change the primary key back to its original value or try the rename again and click Yes.

Triggers for Rec The following triggers are fired in response to the user changing Rec.

OnFindRecord This trigger fires whenever the User causes a FIND to occur on Rec. This happens when the user presses the First or Last buttons or actually uses the Find dialog.

7-6

Navision Attain Solution Development

Adding code to this trigger disables the default code that normally takes place. That default code would look something like this: EXIT(FIND(Which)); This trigger is not normally used. You might need to use it to display something on a form that was not stored in a table, such as an array or temporary table.

OnNextRecord This trigger fires whenever the user causes a NEXT to occur on Rec. This occurs when the user presses the Next or Previous buttons or does anything that causes a Next or Previous (PgUp, PgDown, etc.). Adding code to this trigger disables the default code that normally takes place. That default code would look something like this: EXIT(NEXT(Steps)); This trigger is not normally used. You might need to use it to display something on a form that was not stored in a table, such as an array or temporary table.

OnAfterGetRecord This trigger fires whenever the form must retrieve (or get) a record from the database. It fires for every record being displayed. For instance, on a tabular form that can display 12 records to the user at a time, this trigger would fire 12 times once for every record on the form. This trigger fires right after the record is retrieved from the database. On a tabular form, records are retrieved starting with the current record and moving out. The current is read first, then the next records (those coming after the current), and then the previous records (those coming before the current). This trigger is used a lot for forms. It fires the most often. You can use it to remove filters the user might try to set. This is done on card forms to keep the user from setting a filter on the primary key fields. You could also use it to calculate a calculated column on a tabular form. Always keep in mind that this trigger fires a lot. Too much code in this trigger can slow down your form. Here is how this trigger looks for the Customer Card form. OnAfterGetRecord() SETRANGE("No."); OnAfterGetCurrRecord This trigger fires whenever the Form retrieves the record that is currently selected by the user. It fires right after the OnAfterGetRecord trigger for the current record. It only fires for that record, however, not any other records that

Coding in Forms

7-7

might be displayed on the form.

OnBeforePutRecord This trigger fires whenever the user leaves a record. Its name is misleading. The name suggests that it fires right before the record is modified or inserted in the database, but it actually fires whether the user changes the record or not. Simply hitting the Next or Previous buttons on a form, will cause this trigger to fire before the form leaves the current record. You can use this trigger to see if the user filled in required fields, but this is not necessarily designed for that purpose. This trigger is not used in the base application.

OnNewRecord This trigger fires whenever the user hits F3 or scrolls onto a new record. Note that this trigger fires before the user can even see the new blank record. This trigger is most often used in journal forms. Because it fires before the user can see the new blank record, it is the best place to initialize fields. In most journals there is code in this trigger that copies fields from the previous record, called xRec.

OnInsertRecord This trigger fires whenever the user causes the form to automatically insert the new record. This trigger can stop the insert action. If the trigger returns FALSE, the record will not be inserted. If the trigger returns TRUE, the record will be inserted into the database. This trigger fires before the OnInsert trigger of the source table. If the code in the trigger returns FALSE, the OnInsert of the table will never occur. This is a good trigger to use to make sure all required fields have been filled in. However, the insert may occur right after the primary key fields are filled in. This is usually too early to test the other fields.

OnModifyRecord This trigger fires whenever the user leaves a record that has been modified. This trigger can stop the modify action. If the trigger returns FALSE, the record will not be modified. If the trigger returns TRUE, the record will be modified in the database.

7-8

Navision Attain Solution Development

This Trigger fires before the OnModify trigger of the corresponding table. If the code in the trigger returns FALSE, the OnModify of the table will never occur. This is a good trigger to use to make sure all required fields have been filled in.

OnDeleteRecord This trigger fires whenever the user attempts to delete a record from the form. This trigger can stop the delete action. If the trigger returns FALSE, the record will not be deleted. If the trigger returns TRUE, the record will be deleted in the database. This Trigger fires before the OnDelete trigger of the corresponding table. If the code in the trigger returns FALSE, the OnDelete of the table will never occur. You can use this trigger to check for related records or other conditions that would not allow a delete to occur.

Using a Form as a Timer There is one trigger on a form that does not fit into the prior two catagories. It is called the OnTimer trigger. This trigger is associated with a property as well called TimeInterval. Because the form has the OnTimer trigger and TimeInterval property, each form can have only one timer event.

The TimeInterval Property This property determines when the OnTimer trigger will fire. The value in this property is a number of milliseconds. Once the form is open, the timer begins. After one time interval (the number of milliseconds in the TimeInterval property) the OnTimer trigger is fired. The timer begins again when the trigger finishes. The OnTimer trigger continues to fire until the form is closed.

The OnTimer Trigger This trigger fires in response to the time interval being reached. The trigger will fire whether the form is the active form (has focus) or not. This is a good place to put code that you want to execute every few seconds, minutes, or hours. This trigger is not used in the base application. It could be used if you need to monitor records in a table and periodically export them to a file.

Coding in Forms

7-9

Activity Using the OnTimer Trigger In this activity, you will use the OnTimer trigger and the TimeInterval property of a form to monitor records in a table. Every few seconds, you will display the current number of records in the table.
1 2 3 4 5 6 7 8 9

From the Object Designer, design form 14 (Salespeople/Purchasers). Change the TimeInterval property of the form to 10000 (10 seconds). Add a global variable called TotalCount of type Integer. Add a textbox to the bottom of the form. Set the SourceExpr property of the textbox to TotalCount Add code to the OnTimer trigger to set TotalCount equal to Rec.Count. Add a line to the bottom of the OnTimer trigger that will UPDATE the form. Close and save the form. Run the form.

What is the value of TotalCount for the first minute? What is the value after that? What happens if you add three records?

Using Hyperlink triggers with forms OnHyperlink The C/AL code in this trigger is executed after the OnInit trigger is executed when the form or report that the URL is pointing to has been activated. The syntax is Object.OnHyperlink(URL), where Object is a Form or Report data type and any subtype. The URL is a variable or constant of data type Text or Code.

OnCreateHyperlink The C/AL code in this trigger is executed after the user creates a URL to a report or form. The syntax is Object.OnCreateHyperlink(URL), where Object is a Form or Report data type and any subtype. The URL is a variable or constant of data type Text or Code.

7-10

Navision Attain Solution Development

A user can create a URL for the active form or report by clicking: File, Send, Link by E-Mail File, Send, Shortcut to Desktop File, Edit, Copy Link

C/SIDE will fill in the URL parameter with the default URL strong to the form. However, you can change the default value by changing the contents of the string.

Activity Using the OnCreateHyperlink Trigger When you select either send a shortcut to your desktop or Copy Link the OnCreateHyperlink trigger will be fired. In this activity, you modify the OnCreateHyperlink trigger to force Navision to open a new instance of Navision to display the form.
1 2

From the Object Designer, design form 42 (Sales Order). Add the following code to the OnCreateHyperlink trigger: URL := URL + '&forcenewinstance=yes';

3 4 5

Close and save the form. Run the form. Click on File, Send, Link by E-mail

Notes: You must use the ampersand symbol (&) to separate commands otherwise youll get a message that the text is too long. The Send, Link by E-mail function is integrated with your e-mail system and allows you to send links by e-mail directly from Navision Attain. If you choose to send a Link by E-mail or Report and your e-mail system isnt running youll be prompted to choose the profile. Next, a new e-mail message will be launched and the link will be automatically attached and the subject will contain the name of the form or report that you are on at the time. The recipients open a link by double-clicking the link in the Attach field. Obviously for the link to work it is expected that the person has access to the system that is being referenced.

Coding in Forms

7-11

7.3 Control Triggers


This section divides the control triggers into logical groups. A control may fit into more than one group. In fact, some controls may fit into all groups.

Common Control Triggers This group of triggers apply to most controls. The exceptions are container controls (Tablebox, Tab, Frame) and static controls (Label, Shape, Image, Matrix). Every other type of control has these two triggers.

OnActivate This trigger fires when the user enters the control (this is when the control gains focus). This could be initiated by pressing Tab, Enter, or one of the arrow keys or by using the mouse.

OnDeactivate Fires when the user leaves the control (this is when the control loses focus). This could be initiated by pressing Tab, Enter, or one of the arrow keys or by using the mouse.

Data Control Triggers The following triggers are available on all data entry controls (TextBox, CheckBox, Option Button, PictureBox, Indicator). Both of these triggers fire before focus is actually changed. If an error occurs, the user is left in the control that triggered the event.

OnValidate This trigger fires when the user leaves the control after changing the data. It fires after the field OnValidate trigger of the source table (if the control is bound to a field). No table updates are allowed in this trigger.

OnAfterValidate This trigger fires right after the OnValidate trigger of the control. The difference is that table updates are allowed in this trigger.

7-12

Navision Attain Solution Development

Textbox Triggers Textboxes are the most widely used control in the application. They can be found on most forms. For this reason, they have some special triggers that apply only to textboxes.

OnFormat This trigger fires when the control is about to display a new value. You can use this trigger to change the appearance of the text. There are control functions that allow you to change the fore color, boldness and even the indentation level. This is where you could display negative values in red, for instance.

OnBeforeInput This trigger fires when the user puts focus on the control. It fires before the OnActivate trigger.

OnInputChange This trigger fires every time the user inputs or deletes characters. There is no way to know what exactly was changed.

OnAfterInput This trigger fires when the user leaves the control after changing the field. It does not fire if the user never edited the field(pressing F2 counts as editing). This trigger fires before the OnValidate trigger of the field or control.

OnLookup This trigger fires when the user presses the Lookup button. If any code is in this trigger, the Lookup button will be shown (unless specifically turned off). This overrides (replaces) any code in the OnLookup trigger of the field as well as the default code (normal action of the TableRelation property to allow lookups).

OnDrillDown This trigger fires when the user presses the DrillDown button. If any code is in this trigger, the DrillDown button will be shown (unless specifically turned off). This overrides (replaces) the default DrillDown action of a FlowField. However, the trigger can be used with any type of field (the button will be added to the control).

Coding in Forms

7-13

OnAssistEdit This trigger fires when the user presses the AssistEdit button. If any code is in this trigger, the AssistEdit button will be shown (unless specifically turned off). There is no default action for the AssistEdit button. Code must be in this trigger for the AssistEdit button to do anything.

Button Triggers The following trigger applies only to buttons (Command Buttons, Check Boxes, Option Buttons, and Menu Items). Every type of button has at least this trigger. Menu items have no other triggers except this one.

OnPush This trigger fires when the user clicks (or perhaps hits the space bar) on the button control. For check boxes and option buttons, the value of the source expression is changed before the trigger is fired.

Matrix Box Triggers These triggers are identical to the corresponding Form triggers mentioned before, except that these triggers are linked with the MatrixRec record variable. This is a variable of the Matrix box control and accesses the MatrixSourceTable (see MatrixSourceTable property of the Matrix box control). OnFindRecord OnNextRecord OnAfterGetRecord OnAfterGetCurrRecord OnBeforePutRecord

7-14

Navision Attain Solution Development

7.4 Special Form and Control Functions


In this section, you will learn about many functions that you can use in form and control triggers.

Form Functions Form functions are called through the currForm variable. This variable is a reference to the instance of the current form. The following list of functions is not complete. This is a list of the most useful form functions. See the online help for a complete list.

CurrForm.UPDATE Use this function to save the current record and then update the controls in the form. If you set the SaveRecord parameter to FALSE, this function will not save the record before the system updates the form. You may want to use this function anytime you change Rec or some other variable that is displayed on the form. This will force the form to re-read everything that it is displaying.

CurrForm.Close Use this function to close the current form. Most buttons that close a form (OK, Cancel, Yes, and so on) close it through the PushAction property of the button. If, however, you wanted to run code in the OnPush trigger of the button and then close the form, you would have to manually close the form with this function.

CurrForm.Editable Use this function to return the current setting of the Editable property and to change the setting of the property. Other properties can also be changed from within code, but not all of them can. This property is especially useful if you want to use the same form for viewing and editing, but only some users can edit the records.

Control Functions To access the functions of a control you must name the control first. Then you can use the following syntax: CurrForm.<ControlName>.<Function>

Coding in Forms

7-15

The following list of control functions is not complete. This is a list of the most useful control functions. See the online help for a complete list.

Editable Use this function to return the current setting of the Editable property and to change the setting of the property. Other properties can also be changed from within code, but not all of them can. This property is especially useful if you want to use the same control for viewing and editing, but only some users can edit the field.

Visible Use this function to return the current setting of the Visible property and to change the setting of the property. This property is especially useful if only some users are allowed to view a particular field. Be aware that if you make a textbox not visible in a tablebox control, the user can change that property by going to View, Show Columns.

UpdateEditable Use this function to make a textbox not editable or editable dynamically. It does not change the Editable property. The next time the user enters the textbox, you will have to call this function again to make it editable or not editable. This function can only be called from the OnBeforeInput of the control.

UpdateForeColor Use this function to change the setting of the ForeColor property for a textbox dynamically. You can use this to make negative amounts red or any other color. It changes the color of the text for this record. This function can only be called from the OnFormat trigger of the textbox. This means that it is called just before the user sees the value for the record. On a tabular form, this function would be called for every record.

UpdateIndent Use this function to set the indentation of the text in a textbox. Changing the indentation of the text, allows you to show data in a sort of tree format. This technique is used in the Chart of Accounts.

7-16

Navision Attain Solution Development

This function can only be called from the OnFormat trigger of the textbox. This means that it is called just before the user sees the value for the record. On a tabular form this function would be called for every record.

Activity Identifying the Advanced Features of Common Navision Forms In this activity, you will take a look at some of the advanced features on forms and identify how they work.
1

Go to the Chart of Accounts form on the General Ledger menu. Notice that the first and second columns in the table box have special formatting: Where is the code that does this formatting (name the triggers)? Describe what the code is doing (what are the business rules?).

Go to the Customer Card form on the Sales & Receivables menu. Notice the Assist Edit button on the Number field: Where is the code that runs when this button is pressed (name the triggers)? Describe what the code is doing (what are the business rules?).

Stay in the Customer Card form and look at the code in the OnAfterGetRecord trigger. What is this code doing? Why is it needed here?

Go to the General Journal form on the General Ledger menu. Go to the last line in the Journal and press the Page Down button. Notice that the record has not been inserted but many fields are already filled in: Where is the code that fills in these fields (name the triggers)? Describe what the code is doing (what are the business rules?).

Chapter 8 Low Impact Programming

Low-Impact Programming is the methodology used to create modifications in such a way that they have as little effect as possible on the server and application. This chapter covers the following sections: 8.1 Low Impact on the Application 8.2 Low Impact on the Server 8.3 Low Impact on Network Traffic 8.4 Low Impact on Database Space

8-2

Navision Attain Solution Development

8.1 Low Impact on the Application


In this section, you will learn how to make changes to objects with minimal impact on the existing application. By making changes in this way, you can make future upgrades much faster and safer for your customer.

Tables How can you make changes to tables in the application and allow those changes to be easily upgraded later? Keep in mind the following points: It is better to add a new table than to modify an existing table. If the functionality that you want to add can be done by adding new tables, then that will be easier to upgrade. It is better to add a new field to an existing table than to modify the meaning of an existing field. Adding fields to tables is usually not a problem, but there is a limit to the size of a record. You should never change the meaning of a field even if the field is not used by the base system. The upgrade toolkits are not designed to convert the data if you changed the data type or length of an existing field. There may also be relationships that are added in the new version of the program that conflict with your changes. Avoid this at all costs. It is better to change the name of an existing field than to add a new field if the only purpose is to change the name. If your customer prefers the term client number to customer no., then change the name of the field. Remember that fields are referenced by their numbers not their names.

Reports If you want to make upgrades easier when you modify reports, you should always create a copy of an existing report and modify the copy. This is especially true if there are changes to the layout, since they are so hard to document. Then modify the report menus (documenting these changes) to access these new reports, rather than the original ones. Applies to batch jobs and Dataports as well. If you must modify existing reports, document your changes well. You will most likely have to make those changes again in the next version of the product.

Low Impact Programming

8-3

Codeunits and Code When making modifications to code in a codeunit or any other object, try to write your functionality into a separate function. Then you can call that function from within the existing triggers or functions.

Forms This is where most changes should and will be made. It is also fairly hard to document if you are not careful. Be sure to make a listing before any changes are made and then the documentation will be easy. Copying a form can be more complicated than simply modifying it. Many buttons and properties may be linked to that form.

8-4

Navision Attain Solution Development

8.2 Low Impact on the Server


Always remember that up to 500 users could be attached to the server, so write your code so that the server is bothered as little as possible. Also remember that the user has a computer too, so try to spread the processing as much as possible to the client.

COMMIT The Commit function is handled automatically by the database for almost all circumstances, so this function should almost never be used. Even when the system says you must do so, try to rewrite your code so that it is unnecessary. There should be few reasons to call up a form object while a transaction is in progress.

LOCKTABLE Once a table is locked, none of the other users can use it. Therefore, limit it only to where it is necessary. Remember that an insert, modify, rename or delete will lock the table automatically, so you would not need a Locktable for most modifications.

INSERT, MODIFY, DELETE Try to structure your code in such a way that you do not have to look at the return values of these functions. When you use the return value, the server has to be notified right away so that a response can be obtained. If you do not look at them, the server is not notified until something else requires it. Don't worry, if something really bad happens (out of space, and so on), you will still get the run time error which will roll back your changes.

CALCSUMS, CALCFIELDS Use these two functions whenever possible rather than spinning through records to add things up. Doing one CALCSUMS or CALCFIELDS takes about the same amount of server time as doing one GET.

Low Impact Programming

8-5

Keys Select Keys carefully so that data is obtained in the most efficient order possible. Be especially careful to select keys that support the filters you will be using on the records. In this way, masses of record can be sorted and skipped, without ever having to read the individual records. Also be sure to attach SumIndexFields to the most correct key. You may have a SumIndexField attached to a short key. This key may work for most sums. Then you may attach the same field to another more complicated key that is used occasionally when the user sets several FlowFilters. In this way, the most efficient key will be used.

Validity Testing Many times, you will be testing user input for validity. Whenever you do so, test things that are available without bothering the server first. That way, if they are invalid, you will not waste the server's time. For example, before doing a GET to test the validity of a user's input, make sure that the user entered something. If the field is blank, the GET will most likely fail. So, if the field is blank, you can display an error, without making a server call.

Temporary Tables Temporary tables allow you to minimize the impact on the server in two main areas: reducing the calls to the server and in allowing you to create records that may not yet exist on the server. Reports often need to read from a particular table; however, the report may need to read from the table many different times depending on the processing being done. Therefore, by reading the data once from the server and storing the data in a temporary table we are able to minimize the impact on the server as well as the amount of network traffic. A second example is when working with dimensions there may be times when you want to create data; however, you are not ready to insert the information on to the server. Therefore, by using a temporary table you are able to process the data multiple times based on the dimensions that you are working with in your code. Since the processing is taking place on the client the impact on the server is minimized. Furthermore, once the data has been processed you only have to process the information once from your temporary table instead of making multiple calls to the server.

8-6

Navision Attain Solution Development

8.3 Low Impact on Network Traffic


This is closely related to server access, since all server access takes place over the network. However, it is useful to get the server to do as much work as possible in one network packet rather than the same amount of server work, but taking multiple network packets.

MODIFYALL, DELETEALL Consider setting keys and filters and then using these calls which send only one command to the server, rather than getting and deleting or modifying each of many records, which will send more information back and forth through the network.

CALCSUMS, CALCFIELDS Remember that each of these functions allows you to use multiple parameters to sum many fields with one function call (and one network packet).

Filters Even if a filter is not on a key, it is better to set a filter and have the server skip the records itself, rather than having to get each record and test it yourself before telling the server to get the next record.

Low Impact Programming

8-7

8.4 Low Impact on Database Space


Note that this is lower priority than the above, but still a consideration. The smaller the database is, the faster backups and database tests will run. Most databases will grow, but you can impact this growth in the following ways.

SumIndexFields Note that each SumIndexField takes up a significant amount of space. (They save a lot of time during reports and other data presentation functions, but they take a little extra time during data entry.) Make sure that the amount of time they save will be worth the space that they take up.

Keys Each key takes up a significant amount of space, even without sum fields. Be sure the time they save is worth the space they take. One thing to consider is that if the use for a key (say, a special report) is only significant once a month or once a year, you might deactivate that key and set up a key group so that it can be reactivated without your intervention whenever the user needs it.

Duplication of Data Do not store things like customer names, account descriptions, item descriptions, and so on, in Ledger type records. The same name will then appear numerous times, taking up excess data space. Store the Customer Number, Account Number or Item Number, and so on, instead. Also, use the names or descriptions as defaults for the ledger entry description so that if the user wants it, they can leave it. Note Remember that most of the above rules are broken once in a while in the standard application and that there will be occasions when you will have to as well. Just make sure that it is necessary.

8-8

Navision Attain Solution Development

Chapter 9 The Upgrade Process

This chapter introduces the student to how upgrades are done in Navision Attain. It also describes the tools that can make the upgrade process faster and easier. This chapter covers the following sections: 9.1 Why Upgrade? 9.2 Definitions 9.3 Types of Upgrades 9.4 Planning for Upgrades 9.5 Upgrading the Executables 9.6 Upgrading the Objects 9.7 Tools for Upgrading the Objects 9.8 What If? 9.9 Upgrading the Data

9-2

Navision Attain Solution Development

9.1 Why Upgrade?


There are two very important reasons to upgrade your customers Navision Attain installation.

Your Customer Has Already Paid for It. Our current policy encourages you to sell Upgrade Agreements with every sale, as such many customers will have an upgrade agreement in effect. Our future policy, soon to be in effect, will require you to sell an Upgrade Agreement with every sale. Thus, many of your customers have paid for and will expect an upgrade.

Your Customer Will Pay for It. Some upgrades will be important enough that your customer will want them even if they have not paid for them in advance with an Upgrade Agreement. Also, even with the Upgrade Agreement, the customer is only purchasing the product upgrades and not the installation of the product upgrades. The installation fees could be worth while, if upgrades are planned for and implemented properly.

Benefits to the Customer Gain Access to New Features First, they may gain access to new features. For example, in version 2.60 we have implemented Electronic Payments to Vendors. If your customer does not upgrade to version 2.60, they will not be able to use this feature.

Improvements to Existing Features For example, in version 2.60, there are improvements to financial reporting, budgets, job cost, sales order, contact management, accounts payable and payroll. If your customer would like any of these improvements, they will want to upgrade to version 2.60.

Improved Performance For example, in version 2.60, SQL option, the performance of long batch jobs have been improved a substantial amount.

The Upgrade Process

9-3

Removal of Problems Problems (read bugs) are removed with every single upgrade. In version 2.60, there are 51 bug fixes. Allow Upgrades to new Operating Systems and Hardware

For example when Navision Financials version 2.60 was released, it added support for Windows 2000, didnt include support for SQL 2000. Better Support when on the Current Version

For example when Navision Financials version 2.60 was released, it didnt include support for SQL 2000; however, service pack C was released to add that support. Furthermore, your customer will tend to receive better support when they are on the current version. As versions become obsolete, fewer and fewer people have expertise in that version.

Benefits to the Solution Center Better Customer Relations

Customer Relations are built on providing services to the customer. An upgrade is an opportunity to provide a service to an existing customer that is NOT in response to a customer complaint. It also gives you a chance to talk with your customer and find out what new needs they may have which you could provide for them. Finally, it keeps you in their minds. Easier to Support when the Customer is using the Current Version

In many cases, the solution to a problem your customer has is found in a newer version. In other cases, you may find it hard to support an old product when nobody at your organization can remember it. Remove Problems before the Customer notices them

When your customer finds a problem that turns out to be caused by a bug, they will often want you to fix the problem for nothing, and even if you do (you shouldnt, but), they will be irritated with you and with the product. If an upgrade will fix a bug that the customer has not run into yet, they will pay for it with the upgrade, and there will be one less opportunity for them to be disappointed. Opportunities for Additional Sales

9-4

Navision Attain Solution Development

Navision Attain often includes new features that your customer may be interested in using. However, in order to get this new feature, the customer must upgrade, which generates service revenue for you.

The Upgrade Process

9-5

9.2 Definitions
Before we get into the types of upgrades, we need to explain a few definitions so that we are all talking about the same thing.

Executables The Navision Attain programs that run under the operating system and include the client, the server, the C/ODBC drivers and so on. They can be identified by the fact that you will see them in the Windows or NT Explorer, and they are files that end with .exe or .dll, and so on.

Application The programs that run within the Executables, more specifically within the client, which is known as C/SIDE. The Application is made of Navision Attain objects.

Functional Area A major division within the Application, like General Ledger or Inventory, that can be identified by the fact that there is a Main Menu button that identifies it and by the sub-menu that appears when this button is pressed.

Granule A set of objects that is purchased separately which contains a set of features.

Feature A small set of functions that are part the Application. The General Ledger is a Functional Area within the Application, Account Schedules is a Granule, and Date Comparison is a Feature of Account Schedules.

Bug A piece of the program that does not work as intended. Note that if a piece of the program is not working the way you would like, that does not make it a bug. Only if it does not work as it was intended to work by Navision a/s, is it a bug.

9-6

Navision Attain Solution Development

Enhancement An enhancement is when an existing feature is made to work better in some way, easier to use, faster, performing additional functions, and so on. If a feature is merely made to work as it was originally intended, then that is a bug fix, not an enhancement.

The Upgrade Process

9-7

9.3 Types of Upgrades


There are 4 types of upgrades possible, in order from easiest to most difficult to install:

Improvements Improvements are usually bug fixes, but sometimes include minor new features or feature enhancements; however, no executable changes occur. If there is a data upgrade, it is only a simple procedure to run which will correct any damage a bug might have caused. It is recommended that you have a technical person review each Navision Attain improvement to see whether it applies to any of your customers. The person should determine how long it would take to implement the improvement. Therefore, a determination can be made as to whether you want to schedule time to install the improvement immediately or to wait until there is an improvement that you will install, and install this one at the same time. Do not skip improvements; install them in order.

Service Packs Service Packs will include all previous Improvements, as well as additional bug fixes and/or minor feature enhancements. In addition, they could include changes to the executables. Any data upgrades will be simple procedures which will correct any bug damage. Sometimes, a Service Pack will include the release of a new Product CD. It is recommended that you install every Service Pack, unless you determine that it is completely irrelevant to your customer.

Minor Release Minor Releases will include all previous Improvements and Service Packs. They could also include additional bug fixes, feature enhancements, minor new features and executables changes. In addition, a Minor Release will often include the release of one or more new major features. As a result, there could be minor data upgrades necessary. A Minor Release will always include a new Product CD. You cannot install a Minor Release on your customer site unless your customer has an Upgrade Agreement in force. If they do, you should install the minor release as soon as it can be scheduled. If not, you should review the new features and see if there is anything there that could convince your customer to

9-8

Navision Attain Solution Development

purchase an Upgrade Agreement. Version 2.60, was a Minor Release that included all accumulated improvements since version 2.50. Also included were four (4) new Major Features, Executables changes, no data upgrade and a new Product CD. Furthermore, version 2.60 added support for Windows 2000.

Major Release A Major Release will include all previous Improvements, Service Packs and Minor Releases. It could also include additional bug fixes, minor and major features, and executable changes. Usually, there are major functionality changes included in a Major Release, which means that the way the application works could have been changed. This means that a Data Upgrade will also be required. Also, New Functional Areas could be added to the system, and even new Products or Product Options added. A Major Release will always include a new Product CD. The last Major Release was when we went from version 1.20 to version 2.00. You cannot install a Major Release on your customer site unless your customer has an Upgrade Agreement in force. Since Navision normally does not release the upgrade kit until a month after the Major Release, it gives you time to familiarize yourself with the new features. After becoming familiar with the release, you should discuss with your customer when they would like to upgrade. Please note that this will almost be like installing a new product, it must be well planned and smoothly executed, or it will become a nightmare to your customer, and to you.

The version tells all How can you tell what kind of upgrade you need to perform? Besides the clues we have already given you, the final answer is the new version number. The version number is found in two places. One is on the Help, About screen, which states the version for the Application and for the Executables. The other are the version tags found in the Object Designer, which tell you the version of each particular object. Here is an example showing you how this looks on the Help, About screen. Version US 2.60.B (2.60.B) The number in parenthesis is the Executables version, while the other number is the Application version. The version number has several parts. The Country Version, US, comes first (the world wide version has a W1 here). The Major Release number, 2, is next and the Minor Release number, .60, follows closely

The Upgrade Process

9-9

behind. The Service Pack number, .B, and the Improvement number (none shown) are last. Whichever number was the furthest to the left to be changed, is what sort of release this is. For example, when going from version 2.50 to version 2.60.02, even though both the Minor Release and the Service Pack numbers changed, the one furthest to the left is the Minor Release number, so this is a Minor Release. Please note that on the Help About screen, the Service Pack is usually displayed as a letter, not a number (B, not 2), and the Improvement number is usually not displayed at all. The full number is usually only given on the Version Tags seen in the Object Designer. Also note that the Application Version is set in Codeunit 1.

9-10

Navision Attain Solution Development

9.4 Planning for Upgrades


The most important step in the upgrade process is to plan for it in advance. Well in advance. When you install Navision on your customers system, you know that you will upgrade eventually, so you might as well plan for it. Start this planning when you are making your initial implementation plans. Many times, an upgrade may be made very difficult because of a decision made when you first implement the customers system. The largest area is in customizations. Other areas are also important. For example, an upgrade of the executables usually requires changes on every single client machine. Using Microsofts Systems Management Server (SMS) to install all clients from a single source may save hours during every such upgrade. Throughout the implementation process, keep you customer informed of upgrade considerations. For example, if they do not know that upgrades will bring their system down for a while, they will be irritated when an upgrade is done. If they know in advance, they can help plan by telling you when might be the best time to upgrade. There is no overstating the importance of keeping good records. You must know what is on every customer installation, so you can Make appropriate decisions about whether to install an improvement. Make correct plans about how long an upgrade will take. Know when to ask your customer about whether they want certain new features. Know when an upgrade will override a customization that you have done.

Customizations The most important planning you can do for upgrading is when you are doing customizations. You must consider how you will upgrade your customizations whenever you modify your customers software. The best way to do this is to use the recommended methodology. One thing you will find is that we recommend including considerations for Upgrading with every Design Specification. In addition to helping you plan ahead, it also helps the customer to make intelligent decisions. If they know that a particular design will mean extensive upgrade problems every time, then they may opt for an alternate design, even if it costs more money at first. Also, using the Low Impact programming techniques are part of the Navision

The Upgrade Process

9-11

Attain Development course. Only make changes to the base application when necessary, and then make them in a way that is easy to upgrade. In addition, document every change. This is not optional, this is not just nice, it is essential. You cannot have a smooth upgrade without knowing what is on the customers system. If your customer has development tools, you have additional problems. You need to tell your customer to use the same techniques that you have learned when programming. You need to be copied on all of their documentation.

Scheduling When it is time to actually do an upgrade, the planning starts with scheduling. Once you decide that an upgrade will be done, you must start planning a schedule with your customer well in advance. There are several reasons for this: Navision Server (or SQL Server) must be taken down every time you do an upgrade, no matter how small. Even if there isnt an Executables upgrade, there is an object cache on every client. In addition, a backup must be performed before every upgrade, no matter how small. Treat every upgrade as though you were implementing a new system, since in some ways, you are. Because of the need to take down the server for a period of time, you may need to install the upgrade during off-hours, or even over a weekend, if there is a data conversion as part of the upgrade. There are several things you can do to relieve some of these time issues and make the upgrade less painful for the customer, but they require planning and scheduling. First of all, enlist the support of your customers IT department for anything that they can do for you. For example, the customers IT department can see that the server is taken down and that backups are performed before you get there. Furthermore, they can also distribute Executables changes, and communicate with the users about the upgrade. Second, do as much as possible at your own site. For example upgrade all objects, write and test the data upgrade routines, and finally test the installation. When youve done all this at your site, you are ready to bring everything to your customers site for execution. However, make sure you plan for contingencies - what if things fail.

9-12

Navision Attain Solution Development

9.5 Upgrading the Executables


If there is an upgrade to the executables (the Navision programs that run on the Operating System), this part of the upgrade will always be done first. It can be scheduled separately from any other steps. For example, you could upgrade the Executables portion of a Major Release one weekend, and not schedule the upgrades for the Objects or Data for another 2 or 3 months. Upgrading the Executables is very easy, normally just copying the new files over the old ones. However, when you have 50 or even more Client machines to upgrade, this can take a lot of time. Microsofts Systems Management Server (SMS) is a tool than can be used to reduce the time needed a great deal. Sometimes, the internal database structure could change. The last time was when the maximum record size went from 2,000 to 4,000 bytes with version 2.50. When this happens, you will be told, but all you need to do is make a Navision Backup under the old system, and then restore from the backup after you have installed the new system. The first step is to determine what is being upgraded. This could be an upgrade of Navision Server, the Client, or both. It could also involve other Executables, like C/ODBC. Sometimes, a new Customer License is required. If so, be sure to order one before you proceed. Read the upgrade kit documentation carefully to determine what exactly is upgraded.

Navision Server If you need to upgrade Navision Server, follow these instructions. First, if you need to do a Navision Backup, then make the backup while the old system is still running. This must be a complete backup - all companies, data common to all companies, and application objects. Then, you can have everybody log off the system and bring down Navision Server. Now, make a complete backup copy of all Navision files (executables and database) using tape or another fixed disk drive. This backup will be used should anything go wrong with the upgrade. Now, install the new Server components. This will normally involve copying the new fields over the old ones. Sometimes it will require a new installation, but just install the new version over the old version. Normally, there is a Client also located on the server machine. If so, and if there is an upgrade to the Client Executables, then do this now. If there is a new License involved in the upgrade, copy it into both the server directory (the one which contains server.exe) and the client directory (the one which contains

The Upgrade Process

9-13

fin.exe). If a Navision Backup was required due to a database structure change, you should now delete the old database, bring up the Navision Client on the Server Machine, and create the new database (using the same name and location as before). Restore the complete Navision Backup into this new database. Bring down the Server Machine Client. Now, bring up the Server, and bring up the Server Machine Client. Log onto the Server from the Server Machine Client. Run a few simple tests to make sure that the system has been properly restored and that you can still run basic functionality. If there are Executable upgrades for Clients, bring down the Server now and upgrade all of the clients. We will cover this on the next slide. Once this is done, you can bring the server back up, and you are back on line.

Navision Clients If there are Executable Changes for a Client, the steps are quite simple. Bring down the client (exit Navision Attain). Copy the new Client files into the client directory, or re-install the client; whatever the upgrade kit instructions say. If there are other Executable Upgrades, like C/ODBC, C/FRONT, and so on, then install them now as well. The upgrade kit will include specific instructions. If a new Customer License is required, copy it into the Client directory at this time. Then you can bring the client up. You need to repeat the above steps for every single Client in the installation. If there are many Clients, and you do not have SMS to help you out, you may want to enlist the customers help in doing this part of the upgrade. The steps are very simple, but must be repeated on each system. If the Server Executables are also being upgraded, you must first bring down all Clients, upgrade the Server, Upgrade all Clients, bring the Server back up, and then bring all Clients back up.

9-14

Navision Attain Solution Development

9.6 Upgrading the Objects


The Object Upgrade is the most difficult part of any upgrade, whether it is an Improvement or a Major Release. What makes this difficult? Well, first Navision a/s Headquarters made worldwide changes to the application objects. Next, the NTR makes changes to these same application objects. Then, you made custom changes to these same application objects. In fact, if your customer has the design tools, they may have made their own changes to these same application objects. All without consulting each other! Each NTR is responsible for merging Navision a/s changes with their changes (if applicable), which is why it takes time between the worldwide release of a version and the local NTR release of that same version. It will be your job to merge these changes with the changes that you made during customization. There are many things that help, but as we already pointed out, a lot of them depend on you following the rules for documenting customizations. We will review the Version Tags and Modification Flag rules as we go through the upgrade steps. We will review the basic process that you must go through for each individual application object. For this example, we will use Table 18, the Customer Table, as a stand-in for any application object. For each object, you have a possibility of up to 3 versions. First, the old Base version, which you can get from the CD that you installed from. It is very important that you document what version you installed from. Second, you have the new Base version and also you also have the old Customized version, which is what is running on your customers system right now. What we want when we are through, is a new Customized version of the object, which will include all of the customizations, plus all of the changes that we made for this upgrade. Obviously, there are four possibilities here:

Possibility One First, neither you nor we made any changes to this object. In this case, the object on your customers system will not change during this upgrade.

Possibility Two Second, you customized the object, but we do not change it for this upgrade.

The Upgrade Process

9-15

Again, in this case, the object on your customers system will remain unchanged for this upgrade.

Possibility Three The third possibility is that we change the object for the upgrade, so there is a new base version, but you did not customize this object. In this case, the new object will replace the object on your customers system.

Possibility Four Finally, the possibility that causes the problems - you made customizations to the object, and we also changed the object as part of the upgrade. In this case, you must first determine which version changed the object the most, either your changes, or our changes. Whichever one changed the object the most, you should use that object. Then, you must change that object so that it includes all of the changes that were made by the other. Here is an example. In this case, the upgrade you got from us contains more changes than you made during customization. Therefore, you should get the object that you got from us, re-do your customizations on that object, and then replace the object on your customers system with the new, customized object. Here is another example. In this case, the customizations you made contain more changes than we did for the upgrade. Therefore, you should get the object from the customer system, re-do all of our changes on that object, and then replace the object on your customers system with the new customized object.

An Improvement Lets run through a simple example to explain the steps you need to do to upgrade objects.

The Situation In this situation, you have customized Navision Financials version 2.50 for your customer. You have not installed any improvements for version 2.50.

Customizations You have performed the following small customizations for your customer. First, you have modified the check printing routines in Purchases and Payables to add the company logo to the check. Second, you have added the Customer

9-16

Navision Attain Solution Development

P.O. Number to the Job Card, and you have printed it out on the Budget-toActual report. Finally, you have modified the Purchasing system to add two new boolean fields to the Purchase Order Lines, which are shown as check boxes. The first field is called Expedited and can be checked by the user to indicate that the line has been expedited. The other field is called On Time, and is calculated by the system automatically during posting, by comparing the actual receipt date to the expected receipt date. The total number of objects you have modified is 20, which is a fairly small customization. Since version 2.50 has been released, Navision a/s and your NTR have released several improvements. Several of the objects have been modified and some have been modified more than once. Furthermore, there are also some new objects.

Assumptions Here are the assumptions that we will use for this exercise. First, you have followed all of the recommendations for Version Tags, that is, that in the customers system all modified objects have been tagged with an additional Version Tag (we will use CR01), and that all Modification flags are turned off. Second, your customer has no design tools; therefore, you will not be required to go to the customer site to pick up the objects, since the customer has not changed them. Third, you decide to install all improvements, so that the upgrade to version 2.60 will go smoother. This is a good idea since most of the object changes in version 2.60 are simply to implement the version 2.50 improvements. Fourth, you kept a copy of the customers database in house. This copy has just objects, either no data or minimal (CRONUS International Ltd.) test data. Fifth, you have a coy of the current base application with all improvements installed. If you didnt, you could simply start with a fresh installation of the 2.50 CD and then download the improvements from the web site and load them in. We will assume that you have downloaded the Compare Tool and that you are familiar with how to use it.

The Upgrade Process

9-17

Step by Step Here are the steps involved in the upgrade:


1

Make a working copy of the customers database (objects only). Simply do a Navision backup, create a new database, and then restore Application Objects only. Get the Improved Objects from your Base + Improvements database. To do this, go into the Object Designer and press the All button. Then put your cursor in the Version Tag column, and set a filter to your NTRs code US2.50*. This will filter out all but the improved objects. Then select all objects (ctrl-a) and export. Export as a Navision Attain object file, with an extension of .fob. Go back into your Working Copy database and import the Navision Object file into the Object Designer. Normally, there will be conflicts, but even if there are not, bring up the Object Import Worksheet anyway. Look over all of the objects, find the conflicts, and write down the object type and ID on a Conflict List. Skip any objects that have a conflict for this step. Here is an example of the Object Import Worksheet:

Note that Report Number 10210 has been selected above. It has a little yellow circle with an exclamation point in the Warning column. This means there is a conflict. If you look below, you will see the reason for the conflict. The existing object has the CR01 Version Tag, which indicates it has been customized. However, the new object has a different NTR Version Tag than the existing object, which means it has been upgraded. Since both changes have updated the same object, there is a conflict. We write down the object type and ID

9-18

Navision Attain Solution Development

(Report 10210) and also the Version Tag of the New Object (2.50.00.42) and then, in the Action column, we click the AssistEdit button and select Skip for this object. Note that on this page, there is only one other object conflict Report 10253. For the remaining objects, there is no conflict; the new objects will simply replace the old ones since the old ones were not customized.
4

Review the four possibilities again. First, an object might not have changed in either the customized version or the new base version. In this case, we would not have imported the object, since only the changed objects were imported. These will not show up in the Import Worksheet. Second, the object might only have changed in the customized version, but not in the new base version. In this case, the object will not be imported, since only new base objects are imported. Again, these will not show up in the Import Worksheet. Third, the object might have changed only in the new base version, but not in the customized version. These objects are in the Import Worksheet, but they show up with no conflicts. They can just be imported. Fourth, the object might have been changed in both the customized version and the new base version. These objects are in the Import Worksheet. In this case, they show up with a conflict. Skip these objects (do not import them) and write them down to create a Conflicts List.

Review the Conflicts list. You should look up each object in the Conflicts List in the Change Log that came with the improvements. Remember to check all the improvements, since it might have been modified more than once. If you look at the Change Log in the Latest Improvements page, where they are all together in one log, and you start at the bottom with the version you see in the Import Worksheet, you can find all of the changes more easily. For each object in the Conflicts List, you should ask yourself the question, is the upgrade modification small? More to the point, is it smaller than (or even almost as small as) the change you made for your customization? If the answer to this question is Yes, then use the Change Log that came with the Improvement to implement the improvement on the Customized object in the Working Copy database. If the answer to this question is No, then import the new base object into the Working Copy database, and then use your Change Log to implement the customization on the New Base object.

The Upgrade Process

9-19

Do you not have a change log? Then use the Compare tool to create one. This will also make it easier for you to decide which change is smaller. Either way, set the version tag to reflect both new versions. In this case (Report 10210), the new version tag will be US2.50.00.42,CR01. This shows both the new US Version Tag and the Customization Version Tag. There is one exception to these rules. If this is a table object, we may have added a new field in a number range that you cannot add. In this situation, if at all possible, import the object and then implement your customization on the new object using your change log. If this is not practical, the only alternative is to set the action to Merge Existing<-New and import the new base object. This will bring in the new field(s). Then, apply the remainder of the Change Log.
7 8

Do step 6 for every object on the Conflicts List. The hard part is over. As an optional step, you can change the Version that is displayed on the Help About screen. Note that this step is optional only for an improvement. If this is a Service Pack or a Minor or Major release, you must perform this step.

In the Object Designer, open Codeunit 1 and look for the function called ApplicationVersion. An example is shown here.

Simply change the displayed version to the new version you wish to display, reflecting the latest base version tag in all the object. In this case, it would be US 2.50.00.48. Just change the text between the single quote marks to this text. After you update Codeunit 1 and save it, dont forget to update the version tag

9-20

Navision Attain Solution Development

of this object as well, to the same version as you put in those quotes.
9

The next step is to compile all objects. You do this to make sure there are no conflicts with existing objects that show up. In the Object Designer, press the All button, select all objects, and press F11 to compile them. When it is done, any objects that did not compile will be marked, so you can View, Marked Only, in order to check them out and fix any problems. Now, you must create the Upgraded Objects file. In the Object Designer, select the All button, and then filter the Version Tag column using US2.50.*. Once this is done, change all the Modification Flags to unchecked (off). Select all of the filtered objects (use ctrl-a) and export them as a Navision Object File, a file that has the extension .fob. This is the Upgraded Objects file. Now, finally, you can install the Upgraded Objects on you customer site. First, bring this file to your customer site. You should schedule a non-busy time to do this. When you load objects, especially table objects, sometimes tables are automatically converted or re-keyed, which takes a long time when there is a lot of data.

10

11

12

At the Customer Site, bring down the server. Make a backup copy of the database (enlist the support of the customers IT department for this step). Start the client up which is located on the Server Machine, and open the customers database in Local mode. Now go into the Object Designer and Import the Upgraded Objects .fob file. Remember, even if there are now conflicts, you have already resolved all of them. Therefore, when you bring up the Import Worksheet, all you need to do is press the Replace All button, and then do the import. Once this is completed (it might be 30 seconds, it might be 3 hours or more), compile all objects, then bring down the local client. Bring the Server back up, and your customer can continue working on their newly upgraded system.

The Upgrade Process

9-21

9.7 Tools for Upgrading the Objects


Navision Attain gives you several tools you can use to help you upgrade. Each one may be best for different circumstances.

Import Worksheet You have seen how the Import Worksheet can be a useful tool. It is the best tool to use to rapidly determine object conflicts. It can also be used to add new Objects and Fields in the base number ranges that you may not have permissions for. Finally, as you can see, it is the best tool to use to install the upgraded objects on the customers system.

Editing Text Objects C/SIDE allows you to import Text Objects as well as Navision Attain Objects. This is the best if you have manually applied an automatic change log to some objects. It is also used when importing the Merge Tool results.

Compare Tool The Compare Tool is the best tool to use when you are generating, and printing an Automatic Change Log. It can also export an automatic change log, which is in a good format to use for manual updates. Remember that if you use an automatic change log, it is best to make the change in a text object file and import it as text. Also, the Compare tool helps you find the relative size of each modification by reporting what percent of each object changed. This tool is replaced by Navision Developer's Toolkit in Navision Attain 3.01.

Merge Tool The Merge Tool is the best tool for automatically merging changes. The Merge Tool is used only to merge the objects that have conflicts, in other words, only load the objects (from both the Customized and the New Base versions) into the Merge Tool that you will need to compare and merge. The Merge Tool is also very useful to track and store the various versions that will exist for your various customers. For it to do this properly, you will need to disregard my advice and load all changed objects from both the Customized and New Base versions. This tool is replaced by Navision Developer's Toolkit in Navision Attain 3.01.

9-22

Navision Attain Solution Development

Using the Change Log Many times when we put out an improvement, we also publish a manually generated change log. This is the best tool for documenting modifications that will be implemented many times. However, if you are only implementing the modification once or twice, it is too much work to create. Remember that if you use a manual change log, it is best to make the changes directly in C/SIDE.

The Upgrade Process

9-23

9.8 What If?


In this section, you will explore the answers to many What if questions. These questions usually pop up during the upgrade process, especially for difficult upgrades.

A Major Release Now, we will cover some What Ifs, situations that may happen in your particular upgrade which require some additional information. First, what if this is a major release, not just an improvement. Well, the good news is that, except for the data upgrade, a Major Release is just like an Improvement. Except that it is much, much bigger. Since there are more objects, there will be more chance of conflicts. Since the changes are more extensive, there will be more chances that you will have to re-implement your customization, rather than using a change log to re-implement the upgrade. One suggestion - in your planning, include some time to test the upgraded system, sometime after recompiling all objects but before you set the version tags, reset the modified flags, and export. Make sure that there are no obvious problems. Use the Customer License to do the test, in case there is a problem with it. Once you do the export, you could also test the object upgrade on a copy of the complete customer database (including data). One other possibility is that there could be a major functionality change. This usually means a change in the way something is done. Like the Posting Group changes for version 2.00, for those of you who remember. In this case, the change is so major that you cannot merge the changes, either with the merge tool or even manually. This is because there is a whole new way of doing something, not just a change in the details. If this is the case, you must reimplement your customization from scratch in any object in which there is a conflict. In some cases, your customization may need to be changed even in unchanged objects, should it depend on the old way of doing things.

Field Name Changes What if you made some major field name changes? The problem here is that these changes will ripple down into every other object that refers to the changed field, at least in any automatic change log you generate. This can create huge change logs where in fact there is no actual change to many objects. For example, suppose you changed Department to Division. Now consider the effect on the Customer table. When you change this field name there, you will note that it has now changed automatically on the card form, on the list form, on the Customer List report, and so on, all without you having to

9-24

Navision Attain Solution Development

do anything. However, if you now generate an automatic change log, it will show that the card form changed, the list form changed, the reports changed, and so on. This noise will make it harder for you to do upgrades. The Solution is to make the field name changes first. Before you extract the New Base objects from the new database, make your customized field name changes to the tables only. Any object that you update, you must make sure the Modified Flag is checked, even if you just change the table name. Now, when you extract the new objects, you must get all objects whose Version Tag OR Modified Flag has been changed. Use the Marking Facility to do this. First, filter all objects whose Modified Flag is on, select all of them, and press Ctrl-F1. Then, remove that filter, filter on all objects with the new Version Tag, select all of them, and press Ctrl-F1. Now, remove that filter, use View, Marked Only, and then select all filtered objects.

Customer Has Design Tools What if my customer has the design tools? The problem here is that your customer will probably not follow the Navision Attain development rules. These include rules about setting the Version Tags and Modification Flags, Internal object documentation, developing on line and not using a Project Log, so you cannot tell why they made a change. The Solution has two parts; first, better planning is necessary. You could try to teach your customer the rules, explain how it will make upgrading easier. Or, you could just get them to follow one rule - Leave the Modification Flags alone. This rule is easy to follow, since it does not require them to do anything. When you are going to do an object upgrade, you must schedule a time to pick up the customer database from the customer site before you can upgrade. This is because your copy will not be up to date. Just use a Navision Backup. Make sure when you pick up the backup from your client, you inform them that they should not make any changes until you install the upgrade. Furthermore, reiterate that any changes that they make will not be included in the upgrade. You might also want to identify a customer contact who helped with the development and who can answer any questions about the changes made. The second part of the Solution is that certain steps in the Upgrade Process will be changed. In step 1, when you make the Working Copy of the customer database, be sure to create a new database and restore the Application Objects ONLY from the Navision Backup you got at the customer site. After this, go through and give your customers changed objects (the ones with the

The Upgrade Process

9-25

Modification flag on) their own additional Version Tag, something different from your version tag. Use new letters, based on the customer name. For example, if Acme Tools is your customer, make their Version tag AT01 (assuming this is your first upgrade), and then add a ,AT01 at the end of every modified object with an existing version tag. If the customer created a new object, set the Version tag to AT01 alone. When you reach step 6, (updating each object on the Conflicts list), just remember that you must take into account customer changes. At the least, you will need to generate a new change log from the Working Copy. When you have finished compiling all objects, before you export, you might want to schedule some time for your customer contact to come in and check out the upgraded system. It will be easier to see if a customer change was lost, this way. Finally, when you do export the objects, be sure to get all objects with either the New Base Version Tag, or the Customers new Version Tag that you created. You can use the marking technique to do this. The rest of the steps are the same.

We are not following Navision's Methodology What if you, the Solution Center, is not following the rules? For example, what if you went to the customer site and made some changes on the fly? The answer - see the previous section on what if the customer has the design tools. In addition, you should start following the rules from now on. Upgrades are difficult enough when you follow the rules, without making them even more difficult.

More than one upgrade to do Here is a common situation. The customer has not upgraded for a while, and you have skipped a Minor Release, 2 Service Packs, and a Major Release. Now, with a Minor Release, the customer sees a feature he just has to have, and he realizes that now he wants to be upgraded. The problem, there is no direct upgrade path except from one version to the very next version. You will have to do multiple upgrades at once. Object upgrades can be combined at your site. You simply do the upgrade steps from 2 through 10 for each upgrade version in between. When you have

9-26

Navision Attain Solution Development

upgraded to the final version, you must remember to export all objects with any Version Tag higher than what the customer had, so they will get all changed objects. However, data upgrades are usually too complex to combine. Therefore, you should schedule a separate upgrade for each data upgrade you have to do. This usually corresponds to a major release. Thus, when you combine object upgrades, you must still export the modified objects for each data upgrade. Note that technically, you could do all the data upgrades at once, even if they are not combined. However, it is recommended for safety reasons that you do one data upgrade and then let the system run for at least a couple weeks to shake out any problems before you do the next upgrade (whether or not it includes a data upgrade).

The Upgrade Process

9-27

9.9 Upgrading the Data


Now, we are finally ready to upgrade the data. You will usually need to do this every time there is a Major Release, and sometimes during a Minor Release. We include Data Conversion routines (usually codeunits) in a Upgrade Kit which we generally release about one month after we release the product. You should take advantage of this time lag to familiarize yourself with the new product and any oddities about it. When you get the Data Conversion routines, you should try not to modify them. It would be best if any data conversion routines you needed could be written separately, and then run in series after ours. However, occasionally, you will need to modify our Data Conversion routines because otherwise they would not work with your customizations. This is OK, but just be careful. You must write (or modify) Data Conversion routines at the same time as you are creating the Upgraded Objects on your site. However, these routines must be run on the customer site, in order to upgrade their live data.

Preparation There are some additional steps you must do to prepare for a data upgrade. First, when you make your Working Copy, you should make an additional copy to use to create the Phase One Conversion objects. Phase One objects must be created using the old, un-upgraded database. When you have finished Upgrading the Objects, you should make another copy of the database, this one to be used to create the Phase Two Conversion Objects. Phase Two objects must be created on a new, upgraded database. One other step which you should do, is create a complete copy of the customers database, so that you can test the upgrade process. This means you must get the customer database from the customer site so that you can have complete, current data.

New Field Objects The first thing you will need are the New Field objects. We provide these so that you can create new fields that you wouldnt normally have a license to create. These objects include base tables where the only change is that they contain new fields necessary during the data conversion. These objects may also include scratch tables used as a bridge during the conversion process. These new fields will not have any trigger code. These objects are always brought into the system using the Merge New Into Existing option in the

9-28

Navision Attain Solution Development

Object Import Worksheet. You may need to create some of your own. If so, you may add any field you wish, but just add the Name, Type and Length. Do not put any trigger code in. If you find any, remove it.

Preparing for Phase One Preparing for Phase One of the Conversion. Remember that Phase One of the Conversion is done on the Old Customer Database, the one without any upgrades, but with all customizations. Phase one will also be done with the New Fields objects already loaded. Therefore, the first step to prepare for this is to bring in the Standard, NavisionProvided New Fields objects, then bring in the Navision-Provided Phase One objects. You may modify the standard Conversion Objects, but you should only do this if they will not work as is with your customizations. You should create new Conversion Objects (processing-only reports or codeunits) for your data conversion. What these should do is create or move data into its final home if possible. If this is not possible, then the routine should add the data into a scratch table, and remove it from the original table. When you have written all of your objects, export our objects and yours into two .fob files; one for the New Fields objects, and one for the Phase One Conversion files.

Why Use a Scratch Table? You may wonder why you need to use a scratch table. The reason is usually because a field definition has changed. A Field Type cannot be changed unless no records have data in that field. Therefore, this part of the conversion process will move that fields data, along with its primary key, into a scratch table in the Custom Objects range. Then, the original field can be cleared, so that when the field definition is changed during the object upgrade, there will be no field data in any record, and the change will go though properly. Another reason for a scratch table might be if there is an extensive change to the data structure. The old information might be put into a temporary scratch table and the old table cleared, and then the new data can be placed properly into the heavily modified table (or a brand new table) later after it is brought in with the upgrade objects. An example of this situation would be if in the new data structure, one record will hold information which, in the old data structure was held on two different records in two different tables.

The Upgrade Process

9-29

Preparing for Phase Two Preparing for Phase Two of the Conversion. Remember that Phase Two of the Conversion is done on the New Customer Database, the one with all of the upgrades, plus all customizations. A Phase Two is usually only needed if Phase One put data into scratch tables. Bring in the Standard Navision-Provided Phase Two objects. Again, you can modify these, but only if they will not work with your customizations. You should create your own Data Conversion objects. These should move data from the scratch tables to their final home. Then they should erase the data from the scratch tables. If you know how to do it (examine our objects), you can optionally remove the obsolete fields and tables and scratch tables. When you have finished, export all of the Phase Two objects, both Navision Provided and created by you, into a single Phase 2 fob file.

The Conversion Process Once you have completed all the preparatory steps, including the object upgrade, you should bring all of the above mentioned fob files, including the New Fields, Phase One Conversion, Upgrade Objects and Phase Two Conversion object files to the customer site. This time, you should also bring your Navision Attain Developer license on a diskette, because you will need it to run the data conversion routines. Prepare the customers system as for an object upgrade, by bringing down the server, making a backup copy of the database, and starting the client located on the Server Machine. Using the Tools, License Information, Change option, open your license from the diskette. Now, open the database in local mode. From this local client, perform Phase One of the Database Upgrade. First, bring in the New Fields objects using the Merge New Into Existing option of the Object Import Worksheet. Then bring in the Phase One Conversion Objects. Run the Phase One Conversion in every single company in the database. For each company, run the standard routines, then run your customized ones. Once you have converted all companies, then Import the Upgrade Objects using the Replace All option of the Object Import Worksheet. Now compile all objects as usual. Note that the Phase One Conversion Objects may not compile, but that is OK as they will not be used again. Now, perform Phase Two of the Data Conversion (if any). First, import the Phase Two Conversion Objects using the Replace All option. Then, run the Phase Two Conversion routines in every single company in the database. In each

9-30

Navision Attain Solution Development

company, run the standard conversion routines, then your customized ones. Finally, remove any obsolete objects (if any are mentioned in the upgrade kit) and remove the data conversion objects. Bring down the local client, then bring the Server back up. Please note that all of these steps will take a significant amount of time, especially if your customer has substantial data. You will be able to gauge the amount of time when you do your test run at your site. Be sure that the customer can be down long enough for the entire database and object upgrade. This work will probably be done only on weekends or holidays.

Lab 1 Complex Data Types

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter contains the following sections: 1.1 Running Objects 1.2 Using Dialogs 1.3 Getting Started With Record Variables 1.4 Using Streams

1-2

Navision Attain Solution Development

1.1 Running Objects


In this section, you will run various objects in several different ways.

1.1.1 Running Forms In this exercise, you will create codeunit and add functions to run different types of forms. 1 2 3 4 5 6 From the Tool menu, choose Object Designer. In the Object Designer, click the Codeunit button. Click New. Save the codeunit with the ID 98100 and the Name RunObject. Add a function to the codeunit called RunFormModal. Put code in the function to open the customer list form modally. Do not create a variable. Save the codeunit and test your function by putting code in the OnRun trigger. Add a global variable for form 22 (Customer List) and change your function to use this variable. Save the codeunit and test your function by putting code in the OnRun trigger.

10 Create another function called RunFormNonModal. 11 Add code to the function to run the customer card (form 21) non-modally. Do not create a variable.

12 Save the codeunit and test your function by putting code in the OnRun trigger. 13 Add a global variable for form 21 (Customer Card) and change your function to use this variable. 14 Save the codeunit and test your function by putting code in the OnRun

Complex Data Types

1-3

trigger. 15 Try running the following code in the OnRun trigger: RunFormModal; RunFormNonModal; 16 Now try reversing the lines like this: RunFormNonModal; RunFormModal; What did you notice? What was the difference in the two?

1.1.2 Running Reports In this exercise, you will design a codeunit and add functions to run different types of reports. 1 2 3 Design codeunit 98100 (RunObject). Add a function to the codeunit called RunReportModal. Put code in the function to run the customer listing report modally. Do not create a variable. Save the codeunit and test your function by putting code in the OnRun trigger. Add a global variable for report 101 (Customer - List) and change your function to use this variable. Create another function called RunReportNonModal. Add code to the function to run the Customer - Labels report (number 110) non-modally. Do not create a variable. Save the codeunit and test your function by putting code in the OnRun trigger. Add a global variable for report 110 (Customer - Labels) and change your

6 7

1-4

Navision Attain Solution Development

function to use this variable. 10 Save the codeunit and test your function by putting code in the OnRun trigger. 11 Try running the following code in the OnRun trigger: RunReportModal; RunReportNonModal; 12 Now try reversing the lines like this: RunReportNonModal; RunReportModal; What did you notice? What was the difference in the two?

1.1.3 Running a Codeunit In this exercise, you will design a form and add code to run your codeunit (98100). 1 2 Design form 330 (Main Menu). Add a command button at the bottom of the window next to the Help button. In the OnPush trigger of the command button, add code to run codeunit 98100 (RunObject). Do not create a variable. Save and run the form. Test your button. Change the code to use a codeunit variable. Dont forget to set the subtype. Save and run the form. Test your button. Change the code so that it calls the RunFormModal function, instead of the OnRun trigger. Save and run the form. Test your button.

4 5

6 7

Complex Data Types

1-5

1.2 Using Dialogs


In this section, you will use the dialog variable to display information to the user.

1.2.1 Opening Dialogs In this exercise, you create a codeunit and add functions to it that manipulate a dialog variable. 1 2 3 4 5 6 In the Object Designer, click the Codeunit button. Click New. Save the codeunit with the ID 98101 and the Name ComplexDataTypes. Add a global variable called Window that is of type dialog. Add a function to the codeunit called OpenDialog. Add the following code to that function: Window.OPEN(Processing Customers\ + Customer No. #1#########\ + Progress @2@@@@@@@@@@@@@@@) 7 Save the codeunit and test your function by putting code in the OnRun trigger. Now, add the following line to the bottom of the OnRun trigger: Window.INPUT; 9 Save the codeunit and test your function by putting code in the OnRun trigger.

What changed after you added that line to the OnRun trigger?

Why did you not have to use a Window.CLOSE statement?

1-6

Navision Attain Solution Development

1.2.2 Updating Dialogs In this exercise, you add a function to your codeunit that updates a dialog variable. 1 2 3 4 Design codeunit 98101. Add a global record variable for the Customer table. Add a function to the codeunit called UpdateDialog. Add the following code to that function: Customer.FIND('-'); REPEAT Window.UPDATE(1, Customer."No."); SLEEP(1000); UNTIL Customer.NEXT = 0; 5 Save the codeunit and test your function by putting code in the OnRun trigger. You will have to call the OpenDialog function first and then your new function.

What happens if you comment out the SLEEP statement in the function?

Updating the Progress Indicator


1 2 3

Add a global integer variable called LineNo. Add a global integer variable called TotalLines. Change the code in the function to look like the following:

LineNo := 0; TotalLines := Customer.COUNT; Customer.FIND('-'); REPEAT LineNo := LineNo + 1; Window.UPDATE(1, Customer."No."); Window.UPDATE(2, ROUND(LineNo/TotalLines*10000,1)); SLEEP(1000); UNTIL Customer.NEXT = 0;
4

Save the codeunit and test your function by putting code in the OnRun trigger. You will have to call the OpenDialog function first and then your new function.

Complex Data Types

1-7

1.3 Getting Started With Record Variables


In this section you will create simple functions that perform simple tasks with record variables.

1.3.1 Movement In this exercise, you add a function to your codeunit that moves through a record set. 1
5 6 7

Design codeunit 98101. Add a function called SimpleMovement. Add code to the function to GET customer 50000. Add a message box to the function to display the customer number and name after your GET this: MESSAGE('No.=%1, Name=%2', Customer."No.", Customer.Name);

Save the codeunit and test your function by putting code in the OnRun trigger. Add code to the function to move to the NEXT customer after the GET and before the message. Save the codeunit and test your function by putting code in the OnRun trigger. Change the NEXT statement to go to the previous record. Save the codeunit and test your function by putting code in the OnRun trigger.

10

11 12

Looping through the Records


13 14 15

Create a new function called CustomerLoop. Copy the code from your DialogUpdate function into this function. Save the codeunit and test your function by putting code in the OnRun trigger. You will have to call the OpenDialog function first and then your

1-8

Navision Attain Solution Development

new function.
16

Now change the code so that it starts at the last record and moves backwards through the table.

1.3.2 Modification In this exercise, you will change customer records. 1 2 3 4 Design codeunit 98101. Add a function called SimpleModification. Add code to the function to GET customer 50000. Add code to change the City field to NEW City. Dont forget to MODIFY the record. Save the codeunit and test your function by putting code in the OnRun trigger. Change the function so that it inserts a customer with the following values: No. = 'New 001' Name = 'New customer' Address = 'Somewhere' City = 'Someplace' Phone = '555-5555' 7 Save the codeunit and test your function by putting code in the OnRun trigger. Check to see if your new customer exists. Comment out the insertion code and add code to DELETE that new customer. Remember you must set the No. field before calling delete.

8 9

10 Save the codeunit and test your function by putting code in the OnRun trigger. 11 Check to see if your new customer exists.

12 Put back the code you wrote to insert the new customer. Remove the deletion code. 13 Save the codeunit and test your function by putting code in the OnRun trigger.

Complex Data Types

1-9

14 Make sure the customer exists. 15 Comment out the insertion code and add code to RENAME the new customer to NEW 111. Remember to GET the record first. 16 Save the codeunit and test your function by putting code in the OnRun trigger. 17 Check to see if the customer has been renamed.

1.3.3 Displaying Record Sets In this exercise, you will display the record set of a record variable by passing that variable to a form. 1 2 3 Design codeunit 98101. Add a function called DisplayRecordSet. Add code to the function to Run the Customer List form and pass in the Customer record variable. The code should look like the following: FORM.RUNMODAL(FORM::"Customer List", Customer); 4 Save the codeunit and test your function by putting code in the OnRun trigger. Which Customer is the current record when the form is displayed?

In the OnRun trigger before you call DisplayRecordSet, add code to GET customer 50000. Save and run the codeunit. Which Customer is the current record when the form is displayed?

In the OnRun trigger before you call DisplayRecordSet and after the GET, add code to go to the first customer using find. Save and run the codeunit. Which Customer is the current record when the form is displayed?

1-10

Navision Attain Solution Development

In the OnRun trigger before you call DisplayRecordSet, change the FIND to go to the last customer.

10 Save and run the codeunit. Which Customer is the current record when the form is displayed?

11

In the OnRun trigger before you call DisplayRecordSet, add code to change the current key of the record set to Search Name. Put this code before the FIND statement.

12 Save and run the codeunit. Which Customer is the current record when the form is displayed?

What order are the records in on the form?

13 In the OnRun trigger before you call DisplayRecordSet, add code to set a filter on the Search Name field (use a setfilter statement). The filter should be J..L. Put this code before the FIND statement but after the SETCURRENTKEY. 14 Save and run the codeunit. Which Customer is the current record when the form is displayed?

What types of customers are being displayed?

15 In the OnRun trigger before you call DisplayRecordSet, change the setfilter to a setrange. The filter should be J..L. Put this code before the FIND statement but after the SETCURRENTKEY. 16 Save and run the codeunit.

Complex Data Types

1-11

Which Customer is the current record when the form is displayed?

Are the same types of customers being displayed with the setrange?

17 In the OnRun trigger before you call DisplayRecordSet, change the setrange back to a setfilter. Change the filter so that it is J*|L*. Put this code before the FIND statement but after the SETCURRENTKEY. 18 Save and run the codeunit. Which Customer is the current record when the form is displayed?

What types of customers are being displayed now?

Can you convert this setfilter into a setrange statement?

Youre code in the OnRun trigger should now look like the following: OnRun Customer.SETCURRENTKEY("Search Name"); Customer.GET('50000'); Customer.SETFILTER("Search Name", 'J*|L*'); Customer.FIND('+'); DisplayRecordSet;

1.3.4 Copying Record Sets In this exercise, you will copy record variables in several ways and display the record set to see if it has changed. 1 2 3 Design codeunit 98101. Add a function called FilterRecordSet. Add a new global record variable with a name of Cust2 and a subtype of Customer.

1-12

Navision Attain Solution Development

Add the following code to the function FilterRecordSet. Cust2.SETCURRENTKEY("Currency Code"); Cust2.SETFILTER("Currency Code", '=USD'); Cust2.SETRANGE("No.", '50000', 'ZZZ'); Cust2.FIND('-');

Change the OnRun trigger to call FilterRecordSet and then DisplayRecordSet. Remove any other code. Save and run the codeunit. Did the record set contain the records that you expected?

Why or why not?

7 8 9

Design codeunit 98101. Add a function called CopyRecordSet. Add the following code to the function. CLEAR(Customer); Customer.COPY(Cust2);

10 Change the OnRun trigger to call FilterRecordSet, then CopyRecordSet and then DisplayRecordSet. Remove any other code. 11 Save and run the codeunit. Did the record set contain the records that you expected?

Why or why not?

12 Design codeunit 98101. 13 Add a function called AssignRecordSet. 14 Add the following code to the function. CLEAR(Customer);

Complex Data Types

1-13

Customer := Cust2; 15 Change the OnRun trigger to call FilterRecordSet, then AssignRecordSet, and then DisplayRecordSet. Remove any other code.
17

Save and run the codeunit.

Did the record set contain the records that you expected?

Why or why not?

You may also want to experiment with the record variable functions CopyFilter and CopyFilters.

1.3.5 Using FlowFields In this exercise, you will display the values of a FlowField from a record variable in several different ways. 1 2 3 Design codeunit 98101. Add a function called DisplayNetChange. Add the following code to the function. Window.OPEN(Customer Net Change = #1###########); Customer.FIND('-'); REPEAT Window.UPDATE(1, Customer."Net Change"); Window.INPUT; UNTIL Customer.NEXT = 0; 4 Change the OnRun trigger to call DisplayNetChange. Remove any other code. Save and run the codeunit. You must press the Enter key on the dialog to move to the next record.

1-14

Navision Attain Solution Development

Did the Net Change field have any values?

Why or why not?

6 7

Design codeunit 98101. Add the following code to the DisplayNetChange function right before the Window.UPDATE statement. Customer.CALCFIELDS("Net Change");

Save and run the codeunit. You must press the Enter key on the dialog to move to the next record. Did the Net Change field have any values?

Why or why not?

1.3.6 Creating a Temporary Table In this exercise, you will add records to a temporary table and display the records in a form. 1 2 3 4 5 Design codeunit 98101. Add a global variable named CustTemp with a subtype of Customer. Set the Temporary property of the CustTemp variable to Yes. Add a function called LoadCustTemp. Add the following code to the function. Customer.FIND('-'); REPEAT CustTemp := Customer; CustTemp.INSERT; UNTIL Customer.NEXT(3) = 0; 6 Change the DisplayRecordSet function to display CustTemp instead of

Complex Data Types

1-15

Customer. 7 Change the OnRun trigger to call LoadCustTemp and then DisplayRecordSet. Remove any other code. Save and run the codeunit. Did the record set contain the records you expected?

Why or why not?

1-16

Navision Attain Solution Development

1.4 Using Streams


In this section, you will create and use streams with File data types.

1.4.1 Writing to a File with OutStream In this exercise, you will create a codeunit and add functions to create a file, create the outstream object, and write to the file. 1 2 3 4 5 6 From the Tools menu, choose Object Designer. In the Object Designer, click the Codeunit button. Click New. Save the codeunit with the ID 98104 and the name Streams Test. Add a function to the codeunit called CreateFile. Add two global variables outFile of type File and oStream of type OutStream. Put code in the function to create a new file. In this example we will use a hard coded name of a file ('c:\temp\streamtest.txt'), but you may change this value as needed. The location of the test file is not particularly important. The code should look something like this: outFile.WRITEMODE := TRUE; outFile.TEXTMODE := TRUE; outFile.QUERYREPLACE := TRUE; // You may want to change the filename below outFile.CREATE('c:\temp\streamtest.txt'); 8 Save the codeunit and test your function by putting code in the OnRun trigger to run it. Was the file created?

Create another function called WriteToFile.

10 Add code to the function to create the OutStream object and then use that object to write Hello World into the file.

Complex Data Types

1-17

The code should look something like this: outFile.CREATEOUTSTREAM(oStream); oStream.WRITETEXT('Hello World'); oStream.WRITETEXT; oStream.WRITETEXT; oStream.WRITETEXT('The above two writetext + lines started new lines in this file.'); 11 Save the codeunit and test your function by putting code in the OnRun trigger that first calls the CreateFile function and then calls the WriteToFile function. Make sure you answer Yes to the question about replacing the file since it already exists. Did the file contain the text you expected?

1.4.2 Reading from a File with InStream In this exercise, you will modify the codeunit from the previous exercise and add functions to open a file, create the instream object, and read from the file. 1 2 3 4 5 From the Tools menu, choose Object Designer. In the Object Designer, click the Codeunit button. Open codeunit 98104 (Streams Test). Add a function to the codeunit called OpenFile. Add three global variables inFile of type File, iStream of type InStream, and FirstLine of type Text and length 50. Put code in the function to open an existing file. In this example we will use a hard coded name of a file ('c:\temp\streamtest.txt'), but you may change this value as needed. The location of the test file is not particularly important. The code should look something like this: inFile.WRITEMODE := FALSE; inFile.TEXTMODE := TRUE; // You may want to change the filename below inFile.OPEN('c:\temp\streamtest.txt'); 7 Save the codeunit and test your function by putting code in the OnRun trigger to run it and remove any other code.

1-18

Navision Attain Solution Development

Was the file changed in any way?

8 9

Create another function called ReadFromFile. Add code to the function to create the InStream object and then use that object to read Hello World into the text variable. You may also want to show a message that displays the value of the text variable. The code should look something like this: inFile.CREATEINSTREAM(iStream); iStream.READTEXT(FirstLine); MESSAGE('FirstLine = \' + FirstLine);

10 Save the codeunit and test your function by putting code in the OnRun trigger that first calls the OpenFile function and then calls the ReadFromFile function. Did the message contain the text you expected?

Lab 2 Coding in Tables, Reports and Dataports

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter contains the following sections: 2.1 Coding in Table and Field Event Triggers 2.2 Coding in Report Event Triggers 2.3 Coding in Dataport Event Triggers

2-2

Navision Attain Solution Development

2.1 Coding in Table and Field Event Triggers


In this section, you will add code to various table and field triggers to existing tables in the application to change the way those tables work.

2.1.1 Table Triggers In this exercise, you will add code to the Resource table. 1 2 3 4 From the Tool menu, choose Object Designer. In the Object Designer, click the Table button. Design table 156 (Resource). Put code in one of the table triggers that will default the Name field to whatever the user entered for the No. field. Do this whenever a new record is created in the table. Save the table and test your code by running the Resource Card form. Did your code execute when you expected it to?

Try running the table. Does your code execute at the same time here?

6 7

Design table 156 (Resource). Put code in one of the table triggers that will default the Resource Group field to the first resource group in the resource group table. This should also be done when a new record is created. Save the table and test your code by running the Resource Card form. Did your code execute when you expected it to?

Coding in Tables, Reports and Dataports

2-3

2.1.2 Field Triggers In this exercise, you will add code to the fields in the Resource table. 1 2 Design table 156 (Resource). Put code in one of the field triggers that will ask the user if they are sure about changing the department code. This code should be executed as soon as the user changes and leaves the department code field. (See the Resource Group No. OnValidate trigger for an example.) Save the table. Modify Form 76 Resource Card to include Global Dimension 1 and Global Dimension 2. Save and exit the form. Test your code by running the Resource Card form. Did your code execute when you expected it to?

3 4

Does your code fire if you dont change the field?

What if you change the field to the same value that it had previously?

6 7

Design table 156 (Resource). Find the code in this table that sets the Search Name field to the Name. Change this code to set the Search Name field to the value of the Type field and the Name field. For example, PERSON: MARY. Save the table and test your code by running the Resource Card form. Did your code execute when you expected it to?

Does your code fire when you insert a new record? Why or why not?

2-4

Navision Attain Solution Development

If your code does not fire when a record is inserted, change it so that it does (use the VALIDATE function). How did you do this?

Coding in Tables, Reports and Dataports

2-5

2.2 Coding in Report Event Triggers


In this section, you will add code to reports to change the way that they run.

2.2.1 Showing or Hiding sections In this exercise, you will change a report to allow the user to dynamically cause a section to show or not show on the report. 1 2 3 4 From the Tool menu, choose Object Designer. In the Object Designer, click the Report button. Design report 1404 (Bank Acc. - Detail Trial Bal.). Change the report to allow the user to check a checkbox on the request form if they want to see the detail body section. If the box is not checked, do not show the ledger tables body section (see currReport.SHOWOUTPUT). Save the report and test your code by running it. Did the section show on the report when you ran with the checkbox checked?

Did the section show on the report when you ran with the checkbox unchecked?

Does the report remember whether it was checked or not the next time you run the report? Can you change it so that it will? How did you change it?

2.2.2 Showing User Filters In this exercise, you will add the ability for the user to filter on additional fields, but you will also have to show the filters on the report.

2-6

Navision Attain Solution Development

1 2

Design report 1404 (Bank Acc. - Detail Trial Bal.). Change the report to allow the user to filter the ledger data item on the Work Type field. Save the report and test your code by running it. If you set a filter on the work type field, does the filter show at the top of the report? What about the filter you set on another data item?

4 5

Design report 1404 (Bank Acc. - Detail Trial Bal.). Add a global variable to the report called BankAccountLedgerFilters of type Text250. In the OnPreReport trigger, add code to set the new variable with the filters that the user might have set on the ledger data item such as amount greater or less than a certain value. In the sections designer, add another header to the report to display these filters. It should be on the top of the first page of the report. Add code to the section so that it will only print if the variable is not blank and if it is the first page of the report. (See the code behind the other filter section for an example.) Save the report and test your code by running it. If you set a filter on the work type field, does the filter show at the top of the report?

2.2.3 Using the Skeleton Report In this exercise, you will start with the skeleton report to create a simple report that has a grand total. 1 Design report 50000. (If you have not imported the skeleton report from the class disk, you need to do that first.) Save the report as 98001 and with a Name of Customer Ledgers by Dept. Add the Cust. Ledger Entry dataitem to the report and indent it under

2 3

Coding in Tables, Reports and Dataports

2-7

department. 4 5 Link the two data items. Add a Header and Body section on the report for the Ledger dataitem. (a body section should already exist, if so, use that one). Add the Customer No., Description, and Amount fields to the Cust. Ledger Entry body section. Move the labels to the header section. Add totals for each department to the report. Add a grand total for the entire report without creating a new variable (See the currReport.CreateTotals function). Save the report and test your code by running it.

7 8

Did the totals show up correctly? Did you remember to set the TotalFields property?

2-8

Navision Attain Solution Development

2.3 Coding in Dataport Event Triggers


In this section, you will create a couple of dataports that have code.

2.3.1 Exporting Data In this exercise, you will create an exporting dataport that requires some coding. 1 2 3 4 5 6 7 8 From the Tool menu, choose Object Designer. In the Object Designer, click the Dataport button. Click New. Create a dataport that exports from the G/L Account table. Use a fixed format. It should export the account number and the balance for the account. Only export accounts where the Type is Posting. Finally, add code to round the Balance to the nearest 1000 right before it is exported. Save the dataport with an ID of 98001 and a Name of GL Export 1000. Test your code by running it.

Did the dataport create the file the way you expected?

Did your code run properly?

2.3.2 Exporting Data with a Column Header In this exercise, you will create an exporting dataport that requires some coding. 1 2 Design dataport 98001. Add code to your dataport so that before it exports any records, it writes

Coding in Tables, Reports and Dataports

2-9

out column headings for the data. (Use the currFile variable and the WRITE member function) 3 Save the dataport and test your code by running it.

Did the dataport create the file the way you expected?

2-10

Navision Attain Solution Development

Lab 3 Object Analysis

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 3.1 Exporting and Changing as Text 3.2 Renumbering Objects 3.3 Analysis with impuls Workbench

3-2

Navision Attain Solution Development

3.1 Exporting and Changing as Text


In this section, you will export an object as text, change it, and re-import.

3.1.1 Exporting the Object In this exercise, you will export the customer table.
1 2 3 4 5 6 7

From the Tool menu, choose Object Designer. In the Object Designer, click the Table button. Select table 18 (Customer). Click File, Export. Make sure to select the Text option button. Type in the filename C:\T00018.txt Click OK to export the object to the file. If you had selected more than one object, how many files would you expect to get created?

3.1.2 Changing the File In this exercise, you will add a field to your text version of the customer table.
1 2 3 4 5

From your Start menu, click Run. Enter C:\T00018.txt. Click OK to open the file. Find the last field listed in the FIELDS section. Copy that field to create a new field. Use the number 9000, the name New Field, and the data type Text50. Save the file with your changes.

Object Analysis

3-3

3.1.3 Importing an Object from a Text File In this exercise, you will import your changed customer table back into C/SIDE.
1 2 3 4

From Navision, click Tools, Object Designer. Click File, Import. Type C:\T00018.txt as the filename. Click OK to import the text file. Did you receive any errors? If so, why?

If you received an error about your license, thats good. It means you followed directions. The number that you were given for the field you added is not in your number range. Go back and change your file so that the number of the field is in the range 50000 99999.
5

Re-import the file. Did you get the chance to see the import worksheet?

What happens when you run the customer table?

Compile the table by pressing F11 while it is selected in the object designer. Did it compile successfully?

Can you run the table now?

3-4

Navision Attain Solution Development

3.2 Renumbering Objects


In this section, you will export several objects as text into one file and renumber those objects to a new range.

3.2.1 Importing the project In this exercise, you will import the objects that you need to re-number.
1 2

In the Object Designer, click File, Import. Find the file on your class disk called ObjectAnalysis321.fob. Put the full path and name in the filename text box. Click OK to import the file. This should create several objects in the range 98500-98510. There are tables, forms, reports, dataports, and codeunits. Click on the Version List column in the Object Designer. Press F7 to filter on that column. Enter the filter OA3.2.1 Click OK to filter the objects. Click the All button. You should now see all the objects for this project.

4 5 6 7 8

You could try to re-number these objects to another range by hand, but that would lead to severe problems. All other objects within the project use the number to reference that object. Re-numbering one object would break all of these links. You need a way to change the number of all objects and all references to objects at once.

3.2.2 Exporting All the Objects In this exercise, you will export all of the objects into one file.
1

With the filter applied to the Object Designer and the All button selected, click in the upper left of the table box. This selects all objects within the filter. Click File, Export. Make sure to select the Text option button.

2 3

Object Analysis

3-5

4 5

Type in the filename C:\Renumber.txt Click OK to export all selected objects into one file.

3.2.3 Re-numbering the Objects In this exercise, you will open the file and re-number the objects.
1 2 3 4

From your Start menu, click Run. Enter C:\Renumber.txt Click OK to open the file. Click File, Save As to rename the file and keep a backup. Use the new name C:\Renumbered.txt. Using the Find function (F3) or the Replace function (Search, Replace) of Notepad, find all the object numbers in the range 98500-98510 and change them to be in the range 68500 68510. Be careful that you only change object references and make sure you change them all. You may want to search again after you have changed them all. Save the file with your changes. Remember the new filename is C:\Renumbered.txt.

3.2.4 Importing the Objects In this exercise, you will import the renumbered objects back into Navision Attain.
1 2 3

From the Object Designer, click File, Import. Enter C:\Renumbered.txt in the Filename text box. Click OK to import the objects from the file. What happened?

What error did you receive?

3-6

Navision Attain Solution Development

The error suggests that the objects are duplicate. While the numbers are unique the names are not. You must remove the old versions of the objects or rename them before you can import the new objects from the file.
4

Delete the old objects already in the database (the ones we exported to Renumber.txt). Remember that you have a backup of the text file in case something goes wrong. Try importing the file again. What happened this time?

Everything should have imported without a problem. Test all the objects by compiling them and running them.

Object Analysis

3-7

3.3 Analysis with impuls Workbench


In this section, you will use impuls Workbench to investigate the impact of making changes to the system.

3.3.1 Opening impuls Workbench In this exercise, you will open impuls and the impuls database.
1 2 3

Open impuls Workbench from the Start menu. Click File, Database, Open. Select the impuls workbench database that you created in class. (This should be called Workbench.fdb.) Click OK to open the database. When prompted for company, select only the company. Click OK to open the company. If the Object Administrator does not appear, press F12.

4 5 6 7

3.3.2 Importing New Objects In this exercise, you will import the objects that you renumbered in the last section into impuls.
1 2

Click File, Import. On the General tab, enter a code (FA100) and description (Fixed Asset Project version 1.00) for the objects you are importing. On the Import tab, enter the filename of the file (C:\Renumbered.txt) and set the Update option to Add. On the Keywords tab, you must find and select the Fin.STX file in the Navision Attain, Client folder. (You should not have to change anything on the System tab.) Click Import to import the objects. This may take some time, because as it imports it must build a lot of the relationships between the tables. To check and make sure the objects were imported, expand Tables in the

3-8

Navision Attain Solution Development

tree and look near the very bottom for the Asset table (94001). This was one that you imported.

3.3.3 Using Where Used In this exercise, you will use the Where Used function to find where in the system certain things are used.
1 2

Find the Name field in the Customer table and select it. Right mouse click and click Where Used.

Which table is the last table that uses the customer name?

3 4

Find the Search Name key in the Customer table and select it. Right mouse click and click Where Used.

Which other objects use this key?

3.3.4 Find Table Relations In this exercise, you will use the Relations To and Relations From functions to find out which tables are related to which other tables. Use one of those functions to answer the following questions. Using the Relations To function, find out if the Customer table is related to the Tax Area table. Is it related?

Using the Relations From function, find out if the Item table is related to the Item Unit of Measure table. Is it related?

The answer to both of the above questions should be Yes.

Object Analysis

3-9

3.3.5 Using the Source Finder In this exercise, you will search for key words using the Source Finder function. Answer the following questions by using Source Finder. How many instances of the MODIFYALL function are there only in the Table objects?

How many instances of the word Reserve are there in Field Names?

3-10

Navision Attain Solution Development

Lab 4 Development Methodology

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 4.1 Internal Documentation 4.2 External Documentation 4.3 Setting the Version List 4.4 Completing Design Specifications

4-2

Navision Attain Solution Development

4.1 Internal Documentation


In this section, you will internally document objects that you will import from your class disk. Before starting this lab copy a clean database from your class disk as a starting point. Open this clean database before you start.

4.1.1 Importing the project In this exercise, you will import the objects that you need to document.
1 2

In the Object Designer, click File, Import. Find the file on your class disk called DevMeth411.fob. Put the full path and name in the filename text box. Click OK to import the file. This should modify several base objects (T18, T21, T81, T65700, C12). Click on the Modified column in the Object Designer. Press F7 to filter on that column. Enter the filter Yes. Click OK to filter the objects. Click the All button. You should now see all the modified objects.

4 5 6 7 8

4.1.2 Internally Documenting In this exercise, you will document all the imported objects.
1

With the filter applied to the Object Designer and the All button selected, select table 18. Click Design. In the documentation trigger document what was done to this object. Basically a field was added (it is field number 65701). Remember to use an internal tag (your NSC initials, your initials, and a number).

Save and close the table. Did you remember to tag the field description with your internal tag?

Development Methodology

4-3

4 5

Select table 21. Click Design. In the documentation trigger document what was done to this object. Basically the same field was added.

Save and close the table. Did you remember to tag the field description with your internal tag?

7 8

Select table 81. Click Design. In the documentation trigger document, what was done to this object? Basically the same field was added. There was also some code added. It is currently marked by asterisks (//*************).

Save and close the table. Did you remember to tag the field description with your internal tag? Did you remember to tag the code with your internal tag?

10 11

Select codeunit 12. Click Design. In the documentation trigger document, what was done to this object? Basically there was some code added. It is currently marked by asterisks (//*************).

12

Save and close the codeunit. Did you remember to tag the code with your internal tag?

You do not have to document table 65700. The other developer has already documented this new table.

4-4

Navision Attain Solution Development

4.2 External Documentation


In this section, you will create a project log for all of the objects you just documented internally.

4.2.1 Create the File In this exercise, you will create an empty text file.
1 2 3 4 5

Open Notepad from the Start menu. Click File, New. Click File, Save. Enter the filename C:\CT100.txt. Click OK to save the file.

4.2.2 Adding the Header In this exercise, you will add a header section to your project log.
1

With Notepad still open, add the following information to the top of the file: Name of Project = Customer Type Add-on Solution Center Name of Project Leader = James Doe Customer = Electric Company Inc. Date Started Date Completed Version Tag = CT1.00

You can organize this information in any way that you like. You may want to look at the example in the book. There is other information that would also be good here, but you do not have that information.

Development Methodology

4-5

4.2.3 Adding the Objects In this exercise, you will add an entry for all objects in this project.
1

With Notepad still open, add the following information for every object that is part of this project: Object ID Object Name Objects Documentation trigger

Remember to include all objects that will be exported as part of the project, whether you changed those objects or not.

4-6

Navision Attain Solution Development

4.3 Setting the Version List


In this section, you will set the version list for all objects that are a part of the project and then export all of these objects.

4.3.1 Setting the Version List In this exercise, you will set the Version List for all the objects.
1

With Navision Attain open, filter down to just the objects for this project (using the modified flag). Make sure the All button is selected.

For all modified objects in the list, add the version tag CT1.00 to the end of the version list. If the version list already has something in it, you must separate the new version tag with a comma (for example US2.00,CT1.00).

4.3.2 Unchecking the Modified Flag In this exercise, you will set the Modified flag for all the objects to No.
1 2

Remove any filters in the Object Designer. Filter down to just the objects for this project (this time using the version list filter using *CT1.00*). Make sure the All button is selected. Uncheck all of the Modified Flags for the objects within the filter. You will have to click twice to change the modified flags.

4.3.3 Exporting the objects In this exercise, you will export the objects to take them to the customer site.
1

Filter down to just the objects for this project (this time using the version list filter using *CT1.00*). Make sure the All button is selected. Click in the upper left corner of the table box to select all the objects in the filter. Click File, Export. Enter the filename C:\CT100.FOB. Make sure that the Object format (*.fob) is selected.

3 4

Click OK to export the objects.

Development Methodology

4-7

You may want to re-import the objects and use the import worksheet to check that every object was exported.

4-8

Navision Attain Solution Development

4.4 Completing Design Specifications


In this section, you will complete the design specs for the all day project. This exercise must be done before you can begin the all day project.

4.4.1 Reviewing the Documents Read through the concept document and the design specifications. This should give you an idea of what needs to be done for this customer.

4.4.2 Finish the Specifications For all parts of the project 7.1 7.7, you need to complete the specifications. Some subsections simply say Complete this section. Those sections require you to write the specifications for what needs to be done. For all parts, there is a subsection that lists the objects that will be changed or created. You must analyze the modification and list all of the objects here.

Complete these specifications before attempting the all day project.

Lab 5 Posting Routines

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 5.1 Getting Ready 5.2 Creating Check Line 5.3 Creating Post Line 5.4 Creating Post Batch 5.5 Creating a Starter Routine Post 5.6 Changing a Document Posting Routine

5-2

Navision Attain Solution Development

5.1 Getting Ready


In this section, you will import a journal table and a ledger table (and associated forms). You will use these as a starting point so that you can create posting routines. We will not be using dimensions for posting at this time. Our customers and salespersons are however set up for dimensions. Go to table 352 and delete the dimensions for customers and salespersons if you have not already done so. Also, our GL Accounts are not set up for direct posting. Create a processing only report that will check on direct posting for posting accounts only. "G/L Account"."Direct Posting" := TRUE; "G/L Account".MODIFY;

5.1.1 Importing the Objects In this exercise, you will import the objects that you need for the rest of the exercises in this lab.
1 2

In the Object Designer, click File, Import. Find the file on your class disk called PostingRoutines511.fob. Put the full path and name in the filename text box. Click OK to import the file. This should import four new objects, two tables and two forms (T91511, T91512, F91511, F91512). Run F91511, the journal form, and enter some lines for the journal. This is a journal for entering when items are rented by a customer. If you have trouble selecting items, you need to enter some rentable items in your item table (see 5.1.2 below).

5.1.2 Entering Rentable Items In this exercise you will add items to the item table that have a Base Unit of Measure of HOUR. These are rentable items.
1 2 3

Go to the Item Card. Press F3 to insert a new record. Enter a value in the No. field like CANOE 01.

Posting Routines

5-3

4 5

Enter a description like Canoe, extra wide. In the Base Unit of Measure field, use the lookup button to go to the Item Unit of Measure form. This form will be empty for this new item. On the Item Unit of Measure form, enter HOUR in the first column and leave the second column set to 1. Click OK to set the Base Unit of Measure field. On the Invoice tab, enter a value in the Unit Price field. That is all the fields we need for rentable items. Repeat steps 2-8 at least two more times changing the No. and Description fields. Close the Item Card. Now go back to the journal and add several lines for each rentable item you created.

7 8

10 11

5-4

Navision Attain Solution Development

5.2 Creating Check Line


In this section you will create and test a check line codeunit for the journal that you imported.

5.2.1 Creating the Codeunit In this exercise you will simply create the codeunit.
1 2 3 4 5 6

Open the Object Designer. Click the Codeunit button. Click New. Click File, Save As. Enter the ID 91521 for the codeunit. Enter the name of the journal, a dash, and the words Check Line for the Name. This is the standard name for a check line codeunit. In this case, the name is Rental Jnl.-Check Line.

5.2.2 Setting up the RunCheck function In this exercise you will create and set up the RunCheck trigger for the codeunit. We will be leaving the OnRun trigger empty.
1 2

Create a function called RunCheck. Add a parameter to the RunCheck function called RentalJnlLine with a subtype of 91511 (the rental journal line table). Make sure this parameter is passed by reference (check the Var column for the parameter). Inside the function add a WITH DO statement for the RentalJnlLine record variable. Remember to include a BEGIN and END. All of the code you add to this function should be within the WITH DO statement. Save and close the Codeunit. Attempt to run the codeunit from the Object Designer.

4 5

What happens? Why?

Posting Routines

5-5

5.2.3 Adding Code to the RunCheck Function In this exercise, you will actually create the code that does all the work in the check line codeunit.
1 2

Design the check line codeunit. Add code to the RunCheck function that skips empty lines. An empty line is defined as any line where the Customer No., Item No. and Amount are not filled in. If all of these fields are empty, then exit the function (it is not an error condition). Add code to test the following fields (make sure they are not empty): Posting Date Customer No. Item No. Actual Hours Rented Amount

Add code to make sure the Posting Date field is not a closing date. If the date is a closing date, then an error should be produced that notifies the user of the record that caused the problem and what the problem was. Add code to make sure the Amount field is positive. If the Amount is not positive, then an error should be produced that notifies the user of the record that caused the problem and what the problem was. Save and close the codeunit.

5.2.4 Testing the Codeunit In this exercise, you will add code to a button on the journal form that will call the check line codeunit that you created. Then you will test your codeunit.
1 2 3 4

Design form 91511 (Rental Journal). Open the menu designer for the Posting menu button. Open the C/AL editor for the Check Line menu item. In the OnPush trigger, add code to run your check line codeunit.

5-6

Navision Attain Solution Development

5 6 7 8

Create a global variable for the check line codeunit. Add code to CLEAR the codeunit first. Call the RunCheck function of the codeunit The only parameter is the journal line record variable. Pass in the record variable being used on the form (Rec). Save and close the form. Run the form. Check the lines that you had previously entered. Add new lines that are missing information and check those.

9 10 11

Did your check line routine find all the mistakes? What happens if you check a line that has no customer, item or amount?

Posting Routines

5-7

5.3 Creating Post Line


In this section you will create and test a post line codeunit for the journal that you imported.

5.3.1 Creating the Codeunit In this exercise you will simply create the codeunit.
1 2 3 4 5 6

Open the Object Designer. Click the Codeunit button. Click New. Click File, Save As. Enter the ID 91522 for the codeunit. Enter the name of the journal, a dash, and the words Post Line for the Name. This is the standard name for a check line codeunit. In this case, the name is Rental Jnl.-Post Line.

5.3.2 Setting up the RunWithCheck function In this exercise you will set up the RunWithCheck function for the codeunit.
1 2

Create a function called RunWithCheck. Add a parameter to the RunWithCheck function called RentalJnlLine2 with a subtype of 91511 (the rental journal line table). Make sure this parameter is passed by reference (check the Var column for the parameter). The first line of code in the RunWithCheck function will be to copy the local variable RentalJnlLine2 to a global variable called RentalJnlLine. Create the global variable RentalJnlLine as a record variable of subtype 91511 (the Rental Journal Line table). Add a line of code to the RunWithCheck function to copy RentalJnlLine2 into RentalJnlLine. The second line of code will be to call the Code function. Create a global function called Code (no parameters or return value).

6 7

5-8

Navision Attain Solution Development

8 9 10

Change the Local property of the Code function to Yes. Add a line of code to the RunWithCheck function to call this new function. The last line of code in the RunWithCheck function will copy just the fields that might have changed back into RentalJnlLine2 from the global variable RentalJnlLine. Add an assignment statement that will copy the field values from RentalJnlLine into RentalJnlLine2. Save the Codeunit.

11

12

5.3.3 Adding code to the Code function In this exercise, you will actually create the code that does all the work in the post line codeunit.
1 2

Design the post line codeunit. Add code to the Code function that skips empty lines. An empty line is defined as any line where the Customer No., Item No., and Amount are not filled in. If all of these fields are empty, then exit the function (it is not an error condition). Add code to call the check line routine that you built earlier. Create a global variable for the check line codeunit. Dont forget to set the subtype. Add code to call the RunCheck method of that codeunit variable. You must pass in the RentalJnlLine global variable as a parameter. Add code to lock the ledger table and get the next line number that can be used in the ledger table. Create a global variable for the Rental Ledger Entry table. Create a global variable to hold the NextEntryNo (integer). Add code to the Code function that will only happen once during the posting. It must lock the ledger table. It must go to the last record in the ledger table and put that entry number

3 4

7 8 9

Posting Routines

5-9

into the NextEntryNo variable. It must increment the NextEntryNo variable by one.
10

Add code to make sure that the Item specified exists in the Item table. Do the same for the Customer. Create a global record variable for the Item table. Create a global record variable for the Customer table. Add code to the Code function that will attempt to GET the Item specified from the Item table. If the GET fails an error should be produced that tells the user that the Item does not exist. Add code to the Code function that will attempt to GET the Customer specified from the Customer table. If the GET fails, an error should be produced that tells the user that the Customer does not exist. Add code that creates the ledger record and inserts it. First, INIT the ledger record variable. Set the Entry No. field to the NextEntryNo variable. Set the other fields in the ledger record with the corresponding values from the journal record. Call the INSERT method for the ledger record.

11 12 13

14

15 16 17 18

19

20 Add code to increment the NextEntryNo variable by one. Remember that

the code that set it originally will only be called the first time through the codeunit. The next time through it will use the value already in NextEntryNo.
21

Save and close the codeunit.

5.3.4 Testing the Codeunit In this exercise, you will add code to a button on the journal form that will call the post line codeunit that you created. Then you will test your codeunit.
1 2

Design form 91511 (Rental Journal). Open the menu designer for the Posting menu button.

5-10

Navision Attain Solution Development

3 4 5 6 7 8

Open the C/AL editor for the Post Line menu item. In the OnPush trigger, add code to run your post line codeunit. Create a global variable for the post line codeunit. Add code to CLEAR the codeunit first. Call the RunWithCheck function of the codeunit. The only parameter is the journal line record variable. Pass in the record variable being used on the form (Rec). Save and close the form. Run the form. Post some of the lines that you had previously entered. Run the Rental Ledger Entries form to see if the records were indeed copied to the Ledger.

9 10 11

Did your post line codeunit copy the records correctly?

What happens if you post a line that has no customer, item or amount?

Posting Routines

5-11

5.4 Creating Post Batch


In this section you will create and test a post batch codeunit for the journal that you imported.

5.4.1 Creating the Codeunit In this exercise you will simply create the codeunit.
1 2 3 4 5 6

Open the Object Designer. Click the Codeunit button. Click New. Click File, Save As. Enter the ID 91523 for the codeunit. Enter the name of the journal, a dash, and the words Post Batch for the Name. This is the standard name for a check line codeunit. In this case, the name is Rental Jnl.-Post Batch.

5.4.2 Setting up the OnRun trigger In this exercise you will set up the OnRun trigger for the codeunit.
1 2 3

From within the codeunit, open the properties window. Change the TableNo property to 91511 (the journal table). Press Enter and look at how the OnRun trigger has changed. The OnRun trigger must have a record variable passed in to it. The record variable is passed by reference, has a subtype of Rental Journal Line, and will be referred to by the name Rec. The first line of code in the OnRun trigger will be to copy the local variable Rec to a global variable called RentalJnlLine. Create the global variable RentalJnlLine as a record variable of subtype Rental Journal Line. Add a line of code to the OnRun trigger to copy Rec into RentalJnlLine. The second line of code will be to call the Code function.

6 7

5-12

Navision Attain Solution Development

8 9 10 11

Create a global function called Code (no parameters or return value). Change the Local property of the Code function to Yes. Add a line of code to the OnRun trigger to call this new function. The last line of code in the OnRun trigger will copy just the fields that might have changed back into Rec from the global variable RentalJnlLine. Add an assignment statement that will copy the field values from RentalJnlLine into Rec. Save the Codeunit.

12

13

5.4.3 Adding code to the Code function In this exercise, you will actually create the code that does all the work in the post batch codeunit.
1 2 3

Design the post batch codeunit. Add code to the Code function that makes sure there is something to post. You can use the FIND(-) function to see if any records exist in the Journal table. If FIND returns true, then there are records. If FIND returns false, then there are no records. If FIND returns false, set the Line No. field in the journal to zero and EXIT this codeunit. Remember that post batch does not display messages to the user. If FIND returns true, continue with the codeunit. Add code to open a dialog and display progress to the user. Create a global variable called Window with a type of Dialog. Add code to open the Window variable. Use the following open string:

5 6 7 8

'Processing Rental Journal\' + 'Checking Lines #1##########\' + 'Posting Lines #2########## @3@@@@@@@@@@\'
9

Add code to call the check line routine that you built earlier. This time you must call the check line codeunit for every line in the journal. Create a global variable for the check line codeunit. Dont forget to set the

10

Posting Routines

5-13

subtype.
11

Create a global variable called LineCount (integer). This will count the number of lines that you are processing. Add code to loop through all of the journal lines. Use a REPEAT..UNTIL loop. The FIND(-) has already been done. You simply need to add REPEAT UNTIL RentalJnlLine.NEXT = 0; Within the loop, add code to call the RunCheck method of the check line codeunit variable. You must pass in the RentalJnlLine global variable as a parameter. Within the loop, add code to increment LineCount by 1. Within the loop, add code to UPDATE the dialog variable. Update control id 1 with the value of LineCount. Add code to call the post line routine that you built earlier. You must call the post line codeunit for every line in the journal. Create a global variable for the post line codeunit. Dont forget to set the subtype. Create a global variable called TotalCount (integer). This will hold the total count of the number of lines that you are processing. Add code to set the TotalCount variable to the current value of LineCount.

12

13

14 15

16

17

18

19

20 Add code to reset LineCount to zero. 21

Add code to go back to the first journal line. After your first loop the RentalJnlLine record variable is on the last record in the journal.

22 Add code to loop through all of the journal lines again. Use a

REPEAT..UNTIL loop. The FIND(-) has already been done. You simply need to add REPEAT UNTIL RentalJnlLine.NEXT = 0;
23 Within the loop, add code to call the RunWithCheck method of the post line

codeunit variable. You must pass in the RentalJnlLine global variable as a parameter.
24 Within the loop, add code to increment LineCount by 1. 25 Within the loop, add code to UPDATE the dialog variable. Update control id

2 with the value of LineCount.

5-14

Navision Attain Solution Development

26 Within the loop, add code to UPDATE the dialog variable. Update control id

3 with the value of ROUND(LineCount/TotalCount*10000,1). This is the ratio of the line that it is processing to the number of total lines to be processed. The @ symbols form a progress bar on the dialog.
27 Add code to delete all the journal records from the journal table. 28 Use the DELETEALL method of the RentalJnlLine global variable. 29 Save and close the codeunit.

5.4.4 Testing the Codeunit In this exercise, you will add code to a button on the journal form that will call the post batch codeunit that you created. Then you will test your codeunit.
1 2 3 4 5 6 7

Design form 91511 (Rental Journal). Open the menu designer for the Posting menu button. Open the C/AL editor for the Post Batch menu item. In OnPush trigger, add code to run your post line codeunit. Use the CODEUNIT.RUN function The first parameter is the ID of the codeunit. The second parameter is the record variable. Pass in the record variable being used on the form (Rec). Save and close the form. Run the form. Click Posting, Post Batch to post the journal lines. Run the Rental Ledger Entries form to see if the records were indeed copied to the Ledger.

8 9 10

Did you receive any errors from Check Line or Post Line? What happened to the journal lines as a result of the error? If you received an error, correct the journal lines and post again. What happens to a line that has no customer, item or amount? Are you able to get a glimpse of the dialog? Try adding a SLEEP(500) statement in the loops in Post Batch. What did the SLEEP statement seem to do?

Posting Routines

5-15

5.5 Creating a Starter Routine Post


In this section you will create and test a start routine called post for the posting routine codeunits that you have created.

5.5.1 Creating the Codeunit In this exercise you will simply create the codeunit.
1 2 3 4 5 6

Open the Object Designer. Click the Codeunit button. Click New. Click File, Save As. Enter the ID 91524 for the codeunit. Enter the name of the journal, a dash, and the words Post Line for the Name. This is the standard name for a check line codeunit. In this case, the name is Rental Jnl.-Post.

5.5.2 Setting up the OnRun trigger In this exercise you will set up the OnRun trigger for the codeunit.
1 2 3

From within the codeunit, open the properties window. Change the TableNo property to 91511 (the journal table). Press Enter and look at how the OnRun trigger has changed. The OnRun trigger must have a record variable passed in to it. The record variable is passed by reference, has a subtype of Rental Journal Line, and will be referred to by the name Rec. The first line of code in the OnRun trigger will be to copy the local variable Rec to a global variable called RentalJnlLine. Create the global variable RentalJnlLine as a record variable of subtype Rental Journal Line. Add a line of code to the OnRun trigger to copy Rec into RentalJnlLine. The second line of code will be to call the Code function.

6 7

5-16

Navision Attain Solution Development

8 9 10 11

Create a global function called Code (no parameters or return value). Change the Local property of the Code function to Yes. Add a line of code to the OnRun trigger to call this new function. The last line of code in the OnRun trigger will copy just the fields that might have changed back into Rec from the global variable RentalJnlLine. Add an assignment statement that will copy the field values from RentalJnlLine into Rec. Save the Codeunit.

12

13

5.5.3 Adding Code to the Code function In this exercise, you will actually create the code that does all the work in the post codeunit.
1 2 3

Design the post codeunit. Add code to the Code function that CONFIRMs the users decision to post. Add code that calls the CONFIRM function within an IF statement. The question should be Do you want to post the journal lines?. The default button should be No. If CONFIRM returns false, you must EXIT the Code function. If CONFIRM returns true, you can continue with the codeunit.

4 5

Add code, call the post batch codeunit that you built earlier. Create a global variable for the post batch codeunit. Dont forget to set the subtype. Add code to call the run method of that codeunit variable. You must pass in the RentalJnlLine global variable as a parameter. Add code to check the Line No. field. If the Line No. field is equal to zero, then display a message to the user that says There was nothing to post.. Otherwise continue with the codeunit.

7 8

Posting Routines

5-17

10

Save and close the codeunit.

5.5.4 Testing the Codeunit In this exercise, you will add code to a button on the journal form that will call the post line codeunit that you created. Then you will test your codeunit.
1 2 3 4 5 6 7

Design form 91511 (Rental Journal). Open the menu designer for the Posting menu button. Open the C/AL editor for the Post menu item. In OnPush trigger, add code to run your post codeunit. Use the CODEUNIT.RUN function The first parameter is the ID of the codeunit. The second parameter is the record variable. Pass in the record variable being used on the form (Rec). Save and close the form. Run the form. Enter some valid journal lines and press F11 to Post them. Run the Rental Ledger Entries form to see if the records were indeed copied to the Ledger.

8 9 10

5-18

Navision Attain Solution Development

5.6 Changing a Document Posting Routine


In this section, you will modify the sales document posting routine.

5.6.1 Modifying the Sales Post codeunit In this exercise, you will add code to the Sales Post codeunit so that it rejects any sales lines that have rentable items on them. Rentable items are those that have a Base Unit of Measure of HOUR. This is a simple change.
1 2

Design codeunit 80 (Sales-Post). Find the REPEAT loop that loops through the Sales Line table. This is a large loop that takes up a lot of the OnRun Trigger. Just inside that loop, add code that checks the Unit of Measure Code field. If the Unit of Measure Code field is equal to HOUR, then give the user an error that describes the line that caused the problem and what the problem is. Otherwise, continue with the codeunit.

3 4

5 6 7

Document all of your changes in the standard way. Save and close the codeunit. Test your changes by creating a Sales Invoice that has some rentable items on the lines. You may have to set the Inventory Posting Group field and the Prod. Posting Group field on the items first. Did your document post?

If not, try again.

Lab 6 Data Conversion

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 6.1 Looking at the Import File 6.2 Debugging the Journal 6.3 Building the Transaction Dataport 6.4 Testing the Transaction Dataport 6.5 Changing the Dataport to Post Directly 6.6 Another Exercise

6-2

Navision Attain Solution Development

6.1 Looking at the Import File


In this section, you will open the import file and write down the fields and where they go in the journal. You will also decide what the format is and set other dataport properties.

6.1.1 Inspecting the File In this exercise, you will look at the file that you are going to import.
1 2

Find the file on your class disk called SalesJournal631.txt Double click on the file to open it. What is the file type (Variable or Fixed)? If variable, what is the separator and are there any delimiters? If fixed, fill in the starting position and widths in the table below.

Fill in this table with the necessary information (see information below the table for the mapping of fields):
Mapping For Fixed Starting Field Customer Number Name Invoice Number Invoice Date Due Date Invoice Amount Description Sales Account Journal Field Position Width

To fill in the Journal Field column in the above table, use the following information. The journal that you will be importing into, is the Sales Journal (the table is

Data Conversion

6-3

actually General Jnl. Line). You are creating Customer invoices in that journal. So, the Account No. field will hold the customer number. The customer name is unimportant. The invoice number should be used as the document number. The invoice date should be used as the posting date. There is a due date field in the table, although it is not shown on the form. Be sure the description is brought in correctly from the file. The sales accounts in the file do not correspond to the ones in Navision, so ignore them. However, you will have to have a balancing account on all of these transactions. Use the Accounts Receivable account associated with the Customer Posting Group for that customer.

6-4

Navision Attain Solution Development

6.2 Debugging the Journal


In this section, you will debug the Sales Journal to find out how your dataport should validate and fill in fields. Below is a table with some test data for you to type into the journal.
Field Customer Number Name Invoice Number Invoice Date Due Date Invoice Amount Description Sales Account Value in File 10000 Cannon 12345 03/22/01 04/15/01 1015.74 For Services Rendered FX11345

6.2.1 Getting Ready to Debug In this exercise, you will get the debugger turned on and the journal setup for importing.
1 2

From the Sales & Receivables menu, open the Sales Journal. Click the lookup button on the Batch Name field. This opens the General Journal Batches form. Press F3 to insert a new batch. Enter IMPORT in the Name field. Enter a description, if you want. Clear the No. Series field. You will not need number series for your batch. Click OK to select the IMPORT batch. This returns you to an empty journal. Remove the values from the Posting Date, Document Type, Document No. and any other fields that have a value. The dataport that you will create will not have these fields automatically filled in and neither should this

3 4 5 6 7 8

Data Conversion

6-5

experiment.
9

With the journal ready for importing, click Tools, Debugger, Active. This activates the debugger. Make sure that both Active and Breakpoint on Triggers are checked on the Debugger submenu.

Now you are ready to import your data (by hand). This is done in the next exercise.

6.2.2 Entering the Data and Debugging In this exercise, you will type in information into the journal and observe what code is executed and what other fields might be filled in automatically. You will be filling in the following table to help you create your dataport Change Field triggers OnValidate Document Type Other Fields that are validated

Side effects

Document No. Account Type

Account No.

Description Amount

Balancing Account

Using the mouse click on the first field that you must change (Document Type). Fill the fields from left to right. Type an I into the field and press Enter to select Invoice. This will trigger the debugger to open on any code that is executed. In this case, it stops on

6-6

Navision Attain Solution Development

the Document Type OnValidate trigger. So we know that this field needs to be validated in the dataport. Write Yes in the Change triggers OnValidate column of the table above.
3

Press F5 to see what trigger happens next. The next trigger is the Payment Terms Code OnValidate. So, validating the Document Type field also validates Payment Terms Code field. Write the name of the Payment Terms Code field in the Other Fields that are validated column of the table above. Continue pressing F5 and writing down the names of the fields that are validated in the table. When the debugger window disappears, you are done debugging that field. Look to see if anything else changed in the journal line (where any other fields filled in by the code?). If so, note this in the Side Effects column of the table. Enter the next value for the next field in the table and follow steps 3-5 for that field. Continue until you have debugged all the fields in the journal record. The information in the table will be used in the next exercise to build the dataport.

Data Conversion

6-7

6.3 Building the Transaction Dataport


In this section, you will finally build the dataport that imports into the journal.

6.3.1 Creating the Dataport In this exercise, you will create the dataport and add all the necessary pieces.
1 2 3 4 5 6

From the Object Designer, click Dataport. Click New to open the Dataport Designer. Click File, Save as. Enter the ID 91631 and the Name Sales Journal Import. Open the Properties window for the dataport. Set any properties here such as File Type that you determined in section 6.1. Add a data item to the dataport for the journal table that you will insert into. Add the dataport fields that you determined in 6.1 for this data item. Remember that the order must match the file. If there are any fields that you wish to skip or cannot read directly into the field, use a global variable. Close the Dataport Field Designer. In the OnPreDataItem trigger of the data item, add code to lock and filter the journal table and find the next line number. In the OnAfterGetRecord trigger, add code to validate the fields that need to be validated. You do not need to validate fields that are validated by the OnValidate trigger of other fields that you will validate. In other words, you do not have to validate the Amount field, because it will be validated when you validate the Account No. field. Remember that extra validations slow the dataport down. You may also need to add other code to convert things in the file to the correct data type, or set fields with the values that you stored in variables. Take into account all of the information that is in the table in section 6.2. Add code to this trigger to set the primary key fields as well (all three).

9 10

11

12

13

6-8

Navision Attain Solution Development

14

The last thing you need to do is remove the tab for the data item from the request form (by setting properties) and set the AutoSave to Yes, AutoUpdate to No, and AutoReplace to No. Save, and compile your dataport. You will test it in the next section.

15

Data Conversion

6-9

6.4 Testing the Transaction Dataport


In this section, you will test your dataport and make any necessary changes.

6.4.1 Running the Dataport In this exercise, you will run the dataport created in section 6.3.
1 2 3

From the Object Designer, click Dataport. Run dataport 91631. Enter the full path and filename for the import file (this should be on your class disk with the name SalesJournal631.txt). Click OK to import the file.

Were there any errors? If so, what are they and how might you fix them?

Once fixed, run the dataport again to see if there are other errors.

6.4.2 Checking the results In this exercise, you will look at the records that the dataport imported.
1 2 3

From the Main Menu, click Sales & Receivables. Click Sales Journal. Make sure the selected batch is IMPORT. Count the records and see if the number matches the number of lines in the file.

If you do not have any lines in the journal, run table 81 and see if they have the wrong Template Name or Batch Name. If so, delete them from the table and correct your dataport to set the Template Name and Batch Name correctly. If you have most of the records but not all, try and find out why you are missing some. You may not be setting the primary key fields correctly. If you have all the records, try to post. What error did you get?

6-10

Navision Attain Solution Development

You may notice that certain lines have negative amounts. These negative transactions cannot be considered Invoices. They must be entered as Credit Memos. Erase the journal lines from the journal, design your dataport and change it to set the Document Type to Credit Memo if the Amount is negative. Now, retest your dataport.

Data Conversion

6-11

6.5 Changing the Dataport to Post Directly


In this section, you will copy your dataport and change it so that it posts directly without creating journal lines.

6.5.1 Copying the First Dataport In this exercise, you will save your dataport with a new name and ID.
1 2 3 4

Design dataport 91631. Click File, Save as. Enter the Name Sales Journal Import Post and the ID 91651. Click OK to save the dataport with the new name and ID.

6.5.2 Removing the Unnecessary Code In this exercise, you will remove the code that was used to save information in the journal.
1 2 3 4

With the Dataport Designer still open, select the data item. Click View, C/AL Code. Erase the code in the OnPreDataitem trigger that uses the journal. Erase the code in the OnAfterGetRecord trigger that sets the primary key values or sets the NextLineNo variable. Close the C/AL Editor. Open the Properties window. Change the AutoSave property to No. Click File, Save.

5 6 7 8

6-12

Navision Attain Solution Development

6.5.3 Adding the Call to the Posting Routine In this exercise you add code to call codeunit 12 for the imported journal line.
1 2

Add a global variable for codeunit 12 called GenJnlPostLine. At the bottom of the OnAfterGetRecord trigger, add code to run codeunit 12 using the variable you created. Pass the data item as the record variable parameter. Save and compile the dataport.

Thats it. Run the dataport to test it. Run the general ledger and customer ledger tables to see the records that you posted.

Data Conversion

6-13

6.6 Another Exercise


In this section, you will work through importing beginning inventory. Follow the same outline as in 6.1 through 6.5. Using the Item Journal and the import file ItemJournal661.txt. The scenario is defined below.

6.6.1 Importing Beginning Inventory In this exercise, you will write a dataport that will import Item Journal entries for beginning inventory. The file you will be importing is ItemJournal661.txt from your class disk. The fields in the file are Item number, beginning quantity, unit of measure (does not match the Navision Units of measure), Total value of the inventory. Remember that this is just a test file. The actual file will be much larger. Write your dataport to import the file as it is. Do not change the file first to make the import easier. First, import your values into the Item Journal. Once they are importing and posting correctly, change your dataport so that it automatically posts the journal lines as they are brought in. In the Item Journal, the posting date should be the work date, the entry type is positive adjustment, and the document number should be BEGINV. You should also fill in the Item number, quantity, unit of measure and Amount fields.

6-14

Navision Attain Solution Development

Lab 7 Coding in Forms

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 7.1 Creating a Menu 7.2 Integration with the Main Menu 7.3 Creating a Statistics Form 7.4 Using a Matrix Box 7.5 Using the hyperlink triggers

7-2

Navision Attain Solution Development

7.1 Creating a Menu


In this section, you will create a menu for a functional area. The menu you create will not include all of the features of a standard functional areas menu, but it will include most of them. On your class disk, a file exists that contains objects for a special functional area called the Field of Dreams Funding project. The file is named FieldOfDreams711.fob. Import this file before you begin. As a developer, it is possible to run the various forms and reports directly from the object designer window. A user, on the other hand, would need to access these objects through a menu.

7.1.1 Creating the Form There are several objects in the Field Of Dreams Funding project. As a developer, it is possible to run the various forms and reports directly from the object designer window. A user, on the other hand, would need to access these objects through a menu. In this exercise, you will create such a menu. Its easier to start by copying one of the existing submenu forms and saving it with a new object number and name.
1 2 3 4 5

From the Object Designer, design form 332 (General Ledger Menu). Click File, Save as. Enter the ID 91711 and the Name Field of Dreams Menu. Click OK to save the new form. Change the caption of the large label at the top to Field Of Dreams.

7.1.2 Adding the Buttons In this exercise, you will change the buttons on the menu form to run the objects from the new functional area.
1

Remove all of the buttons (they are the captions with dots beside them) except for Chart of Accounts. Leave Setup and Periodic Activities as well (they are actually menu buttons). Change the Chart of Accounts button to have a caption of Sponsors and to

Coding in Forms

7-3

run the Sponsor Card form.


3

Copy the Sponsors button, change the caption to Report, and set the RunObject property to Report Sp. Pledges & Contributions. Place this button in the upper right corner of the form. Remove all the menu items from setup menu button. This is where you would add supplemental tables. In this functional area, there is only one supplemental table League Team. Add a menu item to the setup menu button that has a caption of League Teams and runs the League Teams form. Remove all the menu items from the periodic activities menu. This menu is used for activities (reports or dataports) that only need to be run once in a while. Add a menu item to the periodic activities menu that has a caption of Import Sponsors and Teams and runs the Team Sponsor Import dataport. Save and close the form. Test the form by running it and clicking the buttons.

Your menu is done.

7-4

Navision Attain Solution Development

7.2 Integration with the Main Menu


In this section, you will integrate the menu you created in section 7.1 with the Main Menu form. A little exploration of the main menu will reveal that it is actually made up of many simple controls. It contains a number of command buttons with picture boxes on the left side and a series of overlapping subform controls on the right. There are also a few image controls that display background images or the logo. Each command button has a corresponding subform control (these are under the logo image) for each functional area (Inventory, Sales and Receivables, and so on). When the user clicks one of the command buttons, code behind the button calls a local function on the form called ChangeSubMenu. This function changes the visible properties of both the current subform (visible property set to false) and the desired subform (visible property set to true). Each of the overlapping subform controls has a SubFormID property that corresponds to a menu form for that functional area. On top of all the subform controls is an image control that displays the Navision logo. It is this control that is visible by default when a user first enters the application.

7.2.1 Adding the Option Button In this exercise, you will add a Command Button and Picture Box for the new functional area. The easiest way to do this is to copy existing ones.
1 2 3 4 5 6 7

From the Object Designer, design form 330. Click on the General Ledger button to select it. Click Edit, Copy. Click Edit, Paste. A new button with the caption General Ledger will appear. Change the caption of the new button to Field of Dreams. With the button selected, press F9 to view the code behind the button. Change the value passed into the ChangeSubMenu function to 91711. (Any number will do as long as it is unique and you use it consistently.) Now, click on the Picture Box control just to the left of the General Ledger button to select it.

Coding in Forms

7-5

9 10 11 12

Click Edit, Copy. Click Edit, Paste. A new picture box will appear. Move it so that it is just to the left of the Field Of Dreams button. Change the source expression property of the picture box to 91711 = CurrentMenuType without the quotes. Save and close the form. Run the form and click your new button.

13

What happens?

7.2.2 Adding the Subform Control In this exercise, you will add a subform control to the Main Menu that will display your new menu form. The easiest way to do this is to copy an existing SubForm control and update the properties for the Field of Dreams Menu.
1 2 3

From the Object Designer, design form 330. Click on the Logo image control. Click Format, Send to Back. This will put the logo image control beneath the subforms. Click on the subform controls to select the top one. There are actually several subform controls stacked on top of each other. Click Edit, Copy. Click off the form itself (click in the gray area outside the form) to unselect the controls. This assures that when you paste, it will go into the top left corner of the form. Click Edit, Paste. A new subform control will appear. Change the name property of the new subform control to FieldOfDreamsMenu. When you copy a control that has a name, the name is copied as well. This causes a lot of confusion if the control is referenced in code. Change the SubFormID property of the new subform control to 91711 (your new menu form). Save and close the form. Run the form and click your new button.

5 6

7 8

10

7-6

Navision Attain Solution Development

What happens?

Why does your subform not display when the form is first run?

7.2.3 Changing the SetSubMenu Function In this exercise, you will complete the changes to the main menu by modifying the code. Remember to document your code changes and make a note of all your changes in the documentation trigger.
1 2 3

From the Object Designer, design form 330. Click on the command button that you added earlier. Press F9 to view the code in the buttons triggers. There is code in the OnPush trigger to call the ChangeSubMenu function. Scroll the editor down so that you can see the ChangeSubMenu function. It calls the SetSubMenu function twice. The first call makes the current subform control (or image control) invisible. The second call makes the users selected subform control visible. Your menu does not show because the code never references it. Add code to the case statement in SetSubMenu for your subform control. Save and close the form. If the main menu is already running close it and press F12 to open it again. Test your modifications, again.

5 6 7 8

Did they work this time? If not, check your code.

Coding in Forms

7-7

7.3 Creating a Statistics Form


In this section you will create a statistics form for the Sponsor table in the Field Of Dreams functional area. It will be run from the Sponsor Card and Sponsor List in the standard way.

7.3.1 Creating the Form In this exercise, you will create the statistics form.
1 2 3 4 5 6 7 8 9 10

From the Object Designer, create a new form. Use the form wizard to create a card type of form. The source table is Sponsor. Add to the form only the FlowFields from the table. Click Finish to close the wizard and open the form designer. Click File, Save as. Enter the name Sponsor Statistics and the ID 91731. Click OK to save the form. Above the FlowField textboxes put a label with a caption of Current. Copy the label and the two textboxes to a new column (to the right of the originals). Create two decimal variables PriorMthContributions and PriorMthPledges. Change the source expression of the two new textboxes to use these variables. Make the two text boxes non-editable. Write code in the OnAfterGetRecord trigger of the form to get the prior months contributions and pledges. Use the date filter to accomplish this quickly. Save and close the form. Test your changes.

11

12

13 14

15

7-8

Navision Attain Solution Development

7.3.2 Linking the Form In this exercise, you will call your statistics form from the card and list forms.
1 2

Design the Sponsor Card form. Add a menu item to the Sponsor button with a caption of Statistics, a short cut of F9, and a push action of RunObject. There is usually a separator before this type of menu item. Add that as well. Change the RunObject property of the menu item to be your statistics form. Change the RunFormLink property to link the forms on No. and DateFilter. Change the RunFormLinkType to OnUpdate. Save and close the form. Test the form by running it and clicking the button. What happens if the card form is on the third sponsor?

3 4 5 6

What happens if you change the sponsor cards record while the statistics form is still open?

Repeat all of these steps for the Sponsor List form.

Coding in Forms

7-9

7.4 Using a Matrix Box


A matrix box should be used in cases where there is a many to many relationship between two tables. In Navision Attain, it is used in the system to show totals by time period such as the Budget forms. From the General Ledger Menu, open the Budgets Window. The relationship displayed there is between the Chart of Accounts and the Date table. There are many G/L Entries per date and many dates that entries were made for each account. A matrix box is the perfect container for such a relationship.

General Description A matrix box is a composite control (comprised of more than one control) that can show information from several tables at the same time. The first two tables are the vertical and the horizontal table of the matrix box control. In the matrix part of the control, each cell can be used to display information that is calculated on basis of fields in these two tables, or information that is retrieved from other tables (with values from the first two tables being used to select records). Each cell in the matrix is the intersection of a record from the vertical and the horizontal table. The part to the left of the vertical divider bar displays records from the vertical table, the table that is the source table of the form, in a way similar to an ordinary table box control. To the right of the divider bar is the matrix itself. Above the matrix, the records from the horizontal table are displayed (in the style that is normally used for the labels in a table box). The title area of this area is the matrix heading. The horizontal table is called the matrix source table. In this example, the vertical table is the G/L Account, the horizontal table is the Date table and the matrix displays budget figures for each combination of account and period.

Navigating in a Matrix Box Navigating in a matrix box is a bit more complex than usual, since there are multiple tables and dimensions involved. The following describes how to move around, both by using the mouse and by using the keyboard.

Using the Mouse It is possible to scroll the vertical table vertically by clicking the navigation buttons at the right of the matrix, and to scroll the horizontal table horizontally

7-10

Navision Attain Solution Development

by clicking the navigation buttons at the bottom of the matrix. If all columns of the vertical table do not fit in the "table box", a normal scroll bar will be added below and you can scroll the columns horizontally, as in an ordinary table box. Resizing of any column is accomplished by placing the cursor in the label area and then dragging when the cursor changes to the resize cursor (which it does when it is on top of a column divider). Dragging the vertical divider bar changes the relative proportions of the table box and matrix box parts. The height of the headings, both in the table box and the matrix part of the control may be adjusted by dragging, and the columns in the table box part can be resized vertically.

Using the Keyboard In order to use the keyboard for navigation, first place the focus in the part of the control to be affected. Using the keyboard, it is possible to move from one part of the control to another by pressing CTRL+<arrow>. That is, to move from the table box to the matrix, press CTRL+RIGHT; to move from the matrix to the matrix heading, press CTRL+UP; to move from the matrix heading back to the matrix, press CTRL+DOWN; to move from the matrix to the table box, press CTRL+LEFT. It is not possible to go directly from the matrix heading to the table box (you have to go via the matrix). When focus is placed in the matrix heading, PAGEUP and PAGEDOWN scrolls the horizontal table (that is, a horizontal scroll). CTRL+PAGEUP or CTRL+PAGEDOWN in the matrix part (including the matrix heading) will also scroll the horizontal table.

Coding in Forms

7-11

7.4.1 Creating a Matrix Box It can be confusing to create a matrix box for the first time. Follow these step-by-step instructions to guide you through the process. You will be creating a matrix box where both the vertical and the horizontal table are based on the Integer table. The matrix cells display the product of the two integers in the records that intersect at that cell. Remember those multiplication tables from grade school?
1

Create a new blank form, and select the Integer table as the source table. The source table for the form will be used as the vertical table of the matrix box, so selecting the correct table is important.

Using the floating toolbar, add a matrix box to the form.

7-12

Navision Attain Solution Development

3 4

Open the Properties window. Set the Name property of the matrix box control to MultTable, and set the HorzGlue and VertGlue properties to Both. Set the MatrixSourceTable property to the Integer Table.

Insert a text box with a source expression of the Number field.

Coding in Forms

7-13

Add a textbox without a source expression to the empty part of the matrix box control. Check the InMatrix property of this textbox - it should be Yes. Add a textbox without a source expression to the last empty part (the matrix heading) of the matrix box control. Check the InMatrixHeading property of this textbox - it should be Yes. Add a source expression to the textbox in the matrix heading (the last one added.) The source expression should point to a field from the MatrixSourceTable. If the matrix box was named MultTable, and the horizontal table is the Integer table, it could be: CurrForm.MultTable.MatrixRec.Number

Add a source expression to the textbox in the matrix. Here, it could be: CurrForm.MultTable.MatrixRec.Number * Number

7-14

Navision Attain Solution Development

10

Save and close the form. Test the form by running it.

What is 12 * 12?

Coding in Forms

7-15

7.5 Using the hyperlink triggers


In this section you will see how to use the hyperlink triggers (OnCreateHyperlink and OnHyperlink) to add the UserID to a Hyperlink and to display a message of who the user was that created the hyperlink when the hyperlink is launched. We shall assume that whenever a Hyperlink is created that the design specifications calls for us to create a newinstance and to add the UserID to the shortcut.

7.5.1 Adding the UserID to the URL In this exercise, you will add the UserID to the URL.
1 2

From the Object Designer, modify form 42 (Sales Order). Add the following code to the OnCreateHyperlink trigger: IF USERID <> '' THEN URL := URL + '&forcenewinstance=yes' + ',UserID=' + USERID;

Create the following variables under the OnHyperlink trigger: UIPos, which is of type Integer and SenderID, which is Text with a length of 30. Add the following code to the trigger: UIPos :=STRPOS(URL, ',UserID='); IF UIPos > 0 THEN UIPos := UIPos + 8; SenderID := COPYSTR(URL, UIPos, MAXSTRLEN(SenderID)); MESSAGE ('The link was created by ' + SenderID);

5 6 7 8 9

Save and Close the form. Run form 42 (Sales Order). Click on File, Send, Shortcut to Desktop. Close the form. Go to your desktop and double click on the shortcut. A new instance of Navision Attain should start up and after logging in you should be brought to the Sales Order that you want to show. Finally, the UserID of the person who created the e-mail should be displayed.

7-16

Navision Attain Solution Development

Lab 8 Property Management

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following sections: 8.1 Introduction 8.2 Concept Document 8.3 Design Specifications

8-2

Navision Attain Solution Development

8.1 Introduction
All Day Project - Property Management Add-On This is the big lab exercise for the Navision Attain Development Course. We have created a project that will put into practice the lessons you have learned to date. This project will take all day to complete. In order to make sure that everyone gets the full benefit of this exercise, you will work individually on this project. If you have any questions on any subject during this project, please raise your hand and wait for the instructor to come to you before asking. On your class disk, you will find all of the files referred to in this exercise. There, you can also find the answer objects. This is not a test. In order to gain full benefit from this exercise, you should not look at the answer objects until we tell you to. Do NOT cheat yourself of the benefits of this exercise. We will first go over the scenario in class and then give you full instructions as to what you are to do. Then, we will turn you loose to work on the project. Take breaks whenever you want after we have completed all instructions.

Scenario This is the scenario that you will be using for this exercise. Read it carefully, as it contains useful information that you will need in order to complete the project successfully.

Background You work for a Navision Solution Center (NSC) as a Certified Attain Developer. The NSC also has a Navision Certified Representative who has been working with the Ted Spinner, the real estate magnate. He has convinced him to purchase Navision Attain to use to manage his many commercial and residential properties. You have been assigned by your boss to perform the modifications necessary for this application. Ted Spinner Enterprises is a real estate holding company solely owned by Ted Spinner. It owns a shopping mall, 6 "strip malls", a large downtown office building, and numerous smaller office buildings throughout the metro area. It also owns 2 high-rise apartments and many other apartment houses both in the city proper and also in the suburbs. Many of these properties have high turnover rates, while in others the tenants stay for many years. Ted Spinner's empire has been created by acquiring properties individually, but mostly by

Property Management

8-3

purchasing other real estate holding companies, many of which had their own computer systems before, and most of which are still using them.

Computerization Project The accounting department at Ted Spinner Enterprises has been working with a hodgepodge of other property management systems from the various acquisitions, plus a homegrown accounting system that they use on many of the individual properties. Now, they would like to have their own accounting AND property management system that they can use for all of their properties. They have chosen Navision Attain because of its flexibility to do exactly what they want, and because of its expandability, since they do not want to convert everything right away. At the beginning, they have decided to computerize their property management functions. They are mainly interested in managing their revenues and tracking their tenants. They want their system in place as soon as possible. If all goes well, they plan on adding other functionality, like Accounts Payable and Payroll.

Preliminary Analysis The Navision Solution Center's Navision Certified Implementation Specialist has already met with the client and discussed their needs. He has determined that Ted Spinner Enterprises will purchase the following Accounting Granules now Basic General Ledger, Basic Receivables, Basic Fixed Assets and the Maintenance and Insurance granules that go with Fixed Assets. They will purchase Basic Payables and the Payroll granules later. The Implementation Specialist has also determined that they will need to get some customizations in order to do their tracking the way they desire. They have determined that the Fixed Assets granules will track their expenses on a per property basis just fine. However, they wish to track their revenues on a per tenant space basis. They have agreed to get these modifications on a time and materials basis. Once these are done acceptably, they will want to allocate expenses on a per tenant space basis as well.

The Assignment The Implementation Specialist has also met with your Senior Developer and with the client and worked out the Concept Document and most of the Design Specifications. You are assigned to complete these Design Specifications and the preliminary modifications within 8 hours. Once these are completed, of course there will be others before the completed package is delivered to the customer.

8-4

Navision Attain Solution Development

The Navision Representative believes that if this is done well, he can sell this type of system to other property management companies in the area. Therefore, the Senior Developer has instructed you to write this in such a way that it can be used as an add-on and sold to other customers. For this purpose, he has assigned you Object Numbers from 99300 through 99309 and a Version Tag of NSC013. He wants you to complete all standard programming documentation (including a Project Log, internal documentation, and a Change Log) for this project. User manuals and online help can wait until later.

Instructions Review the Concept Document and the Design Specifications which follow this introduction and are also located on your class disk. You will need to copy the Design Specifications to your own system in order to modify it. Note Requirements 7.5 and 7.7 are not completed in the Design Specification. You must complete them, and complete the estimate for the entire project. Note that labor is charged at $125.00 / hour. You may change the estimates on the other requirements of the project, except for the Specification estimates, since they were already done except for 7.5 and 7.7. When you figure out your complete estimate, write it out on a piece of paper with your name on it and give it to the instructor. When you are ready to start programming, start with a copy of a fresh, unmodified database. Make your modifications, making sure to keep the following things in mind: Follow Navision Standards in all aspects of this project. Do your internal documentation as you go. Keep your project log up to date as you go. Track your time on each Requirement as you go. Update the Design Specification with the Objects actually used as you go.

When you are ready for the Dataport, note that the customer has provided a file on your class disk, called "tspaces.txt". It has the following fields and fields in

Property Management

8-5

it, in this order: Fixed Asset No. Tenant Space Tenant No. Monthly Rent Deposit Size

For the best results, you should create the Fixed Assets that are in the Dataport before you test-execute the Dataport. These are: PARKPLAZA MEDOFFICE1 MEDOFFICE2 PARKVIEW

Be sure to test your program thoroughly, using the imported Tenant Spaces and the Automatic Billing to increase the amount of data being tested. Test as many cases as possible.

Deployment Once you have completed your programming and completed the testing, go through the steps necessary to deploy the product, including setting the Version tags, and exporting all modified or new objects as both an fob and a txt file. Note the objects you have modified from the base application and then switch to the original fresh, unmodified Navision Attain database from which you started. Mark those modified objects and export them as text. Use the two text files to create a Change Log, using the Merge Tool, the Compare Tool or Navision Developer's Toolkit.

Billing and Review Now, complete the billing cycle by coming up with an actual amount to bill the customer, using your actual hours and actual objects needed to run the fob file

8-6

Navision Attain Solution Development

you extracted. Write this up on a piece paper with your name to give to the instructor. Be prepared to show your project to the class. To do this, copy the fob file, the updated Design Specification, your Project Log and your Change Log to a diskette.

Property Management

8-7

8.2 Concept Document


It has been determined that the existing Fixed Assets granules will be sufficient for tracking expenses on a per-property basis. Each building will be considered one Fixed Asset. It is also required that revenues and expenses be tracked on a per tenant basis. For this first phase, we will track revenues only on a per tenant basis. Expenses per tenant will be added during the second phase.

Modifications to Basic Receivables The Basic Receivables granule is perfectly acceptable for our purposes, except for one thing - our Customers are called "Tenants". Make the appropriate name changes throughout our system. Do not change any existing reports at this time. Limitation: Since Ted Spinner Enterprises is only purchasing Basic General Ledger, Basic Receivables and Fixed Assets, only these areas will be modified.

Modifications to Basic Fixed Assets The Fixed Assets granules will work as is for tracking expenses on a per property basis. Modifications are needed to add the ability to track revenues on a per Tenant Space basis.

Allow Posting of Revenue Entries Add the fields necessary to support the posting of Fixed Asset (Property) revenues to the General Ledger. This will include adding a Revenue Account field to the Fixed Assets Posting Group, and adding a number series to the Fixed Asset Setup to generate document number automatically.

Fixed Assets Menu Add the ability to access the Tenant Journal, which is described in section 7.4.

Tenant Spaces Each individual office, apartment, shop or store within a property is called a Tenant Space. There are multiple Tenant spaces per property (Fixed Asset).

8-8

Navision Attain Solution Development

Tenant Space Maintenance A table should be created that is Subsidiary to the Fixed Asset table. The Tenant Space Card should be accessible from the Fixed Asset card and should allow the entry of the space number, size (in square feet), monthly rent, amount of security deposit, and Tenant No. if occupied (Tenant No. is to be blank if unoccupied).

Lookup Tenant Spaces from Tenant Card Allow user to look up, from the Tenant Card, a list all Tenant Spaces occupied by that Tenant.

Property Information On the Fixed Assets Card, add a tab (called Tenant Spaces) which will contain 4 fields. These fields will show, for this property, the number of Tenant Spaces, the total size (square feet) of all Tenant Spaces, the total deposits and the total monthly rent. The last two must only be counted if the tenant space is actually occupied.

Property List Report Create a report that will list all properties and for each one will list all Tenant Spaces. Important note: Not all Fixed Assets are Properties. Only include those with Tenant Spaces.

Tenant Journal Entries Allow the user to make Journal Entries for Tenant Revenue. This will be called the Tenant Journal.

Tenant Journal The user must be able to enter a Fixed Asset, Tenant Space and Date. The Tenant can be defaulted or entered, and the Amount is the Amount charged to the Tenant. Limitation: Only one Journal is needed, so there will not be any Journal Templates or Journal Batches.

Property Management

8-9

Automatic Filling of Tenant Journal There will be a way to automatically fill the journal with one or more properties. Fill the Journal with all the currently rented spaces, and the Monthly Rent as the amount. Allow the user to modify the entries before posting. This function should be called from the Journal.

Tenant Space Ledger The entries entered into the Journal will be posted into a Ledger. This ledger can be viewed from the Tenant Space Card

Tenant Space Transaction Report Create a report that will show Ledger Entries per Tenant Space, including a total per Tenant Space, a total per Fixed Asset (property) and a Grand Total. Allow user to enter a Date Filter so this report can be from a particular Date Range.

Tenant Space Information Add a FlowField to the Tenant Space Card (not the list) which shows the total transactions in the Ledger for this Tenant Space. Be sure to take the Date Filter into account.

Posting The Tenant Journal must be able to get posted to the Tenant Ledger. It should also post to the General Ledger at the same time. The Debit goes to the Tenant, and the Credit goes to the Revenue Account mentioned in section 7.2.1. The Document Number should be automatically generated (see same section). Make sure dimensions have been deleted from table 352 Default Dimension and direct posting has been checked on in table 15 GL Account.

Data Conversion A Tenant Space text file will be created by Spinner Enterprises. It will be a flat file, with fixed length fields, one Tenant Space per line. It must be imported into Navision Attain to initialize the Tenant Space table. A test file will be provided.

8-10

Navision Attain Solution Development

8.3 Design Specifications

Property Management Project


for Ted Spinner Enterprises

Table of Contents
Requirement
7.1: 7.2: 7.3: 7.4: 7.5: 7.6: 7.7:

Description

Page

Modifications to Basic Receivables ........................................................11 Modifications to Basic Fixed Assets....................................................... 14 Tenant Spaces ....................................................................................... 17 Tenant Journal .......................................................................................20 Tenant Space Ledger .............................................................................23 Posting ..................................................................................................26 Data Conversion ....................................................................................29

Property Management

8-11

7.1: Modifications to Basic Receivables


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Change "Customer" to "Tenant". Approved you 0.5 $62.50 0 0 $0 $62.50

Part 1:

Technical Specifications

7.1.1. Function
The Basic Receivables granule is perfectly acceptable for Spinner's purposes, except for one thing - their Customers are called "Tenants". Make the appropriate name changes throughout the part of the system they are purchasing.

7.1.2. Value
Spinner's business calls for them to call their customers "Tenants".

7.1.3. New Functionality


Modify the following objects so that every instance (that the end user can see) of "Customer" is replaced by "Tenant": Tables: Customer Customer Ledger Entry General Journal Line

8-12

Navision Attain Solution Development

Forms: Customer Card Customer List Customer Ledger Entries Sales & Receivables Menu

Part 2:

Limitations

Do not change any existing reports at this time. Since Ted Spinner Enterprises is only purchasing Basic General Ledger, Basic Receivables and Fixed Assets, only these areas will be modified.

Part 3:

Estimate
Hours 0.1 0.3

Work Element Specification Programming Testing Documentation Total

0.1 0.5

Part 4:

Impact on Upgrades

This Requirement will have some impact on upgrades. We recommend that whenever an upgrade is received, this requirement be re-implemented using the Change Log. We estimate that this will take 0.2 hours per upgrade.

Part 5:

Approval

The customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Property Management

8-13

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

8-14

Navision Attain Solution Development

7.2: Modifications to Basic Fixed Assets


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Tracking Revenues per Tenant Space Approved you 0.8 $100.00 0 0 $0 $100.00

Part 1:

Technical Specifications

7.1.4. Function
Add the fields necessary to support the posting of Fixed Asset (Property) revenues to the General Ledger. This will include adding a Revenue Account field to the Fixed Assets Posting Group, and adding a number series to the Fixed Asset Setup to generate document number automatically. Also, add the ability to access the Tenant Journal.

7.1.5. Value
Allows posting of revenues to the General Ledger while we post Tenant Journal Entries.

7.1.6. Current Functionality


Fixed Asset Posting Groups are only used to post expenses currently. For this reason, they are assigned at the Depreciation Book level. This functionality will remain unchanged.

7.1.7. New Functionality


To the FA Posting Group table, add a field called Revenue Account. Like the other account numbers located there, it should be table related to the G/L Account Table. The form used to edit these posting groups should be updated

Property Management

8-15

accordingly. To the Fixed Asset table, add a field called FA Posting Group Code. This field should be table related to the FA Posting Group table. Add this field to the Posting tab of the Fixed Asset Card. Also, to the FA Setup table, add a field to hold the new Tenant Charges No. Series. Like the other No. Series, it should be table related to the No. Series table. The Fixed Asset Setup form should be updated to allow the user to enter this field. The Fixed Assets Menu should be modified to add access to the Tenant Journal (see section 7.4 for creation of Journal) from it. Include it in the same area as the current Journal menu items.

Part 2:

Limitations

The current functionality, including the fact that the FA Posting Groups are assigned to a Depreciation Book for expense posting purposes, will not be modified.

Part 3:

Estimate
Hours 0.2 0.4

Work Element Specification Programming Testing Documentation Total

0.2 0.8

Part 4:

Impact on Upgrades

This Requirement will have some impact on upgrades. We recommend that whenever an upgrade is received, this requirement be re-implemented using the Change Log. We estimate that this will take 0.3 hours per upgrade.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

8-16

Navision Attain Solution Development

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

Property Management

8-17

7.3: Tenant Spaces


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Track the Tenant Spaces in each Property (Fixed Asset) Approved you 1.8 $225.00 1 4 $336.00 $561.00

Part 1:

Technical Specifications

7.1.8. Function
Each individual office, apartment, shop, or store within a property is called a Tenant Space. Subsidiary table will be created, related to the Fixed Asset table. This will allow each Tenant Space to have its own data, plus revenue transactions tracked for it. Tenant Space can be looked up from Fixed Asset Card and from Tenant Card. Fixed Asset Card will contain summary information about all Tenant Spaces. A Property List report will show all Tenant Spaces per Fixed Asset.

7.1.9. Value
Will allow valuable rental data to be accessed in an easy fashion, both on screen and in a report.

7.1.10.
None.

Current Functionality

7.1.11. New Functionality


Create a Subsidiary Table called FA Tenant Space, related to the Fixed Asset

8-18

Navision Attain Solution Development

table. Each record should contain a field to relate back to the corresponding Fixed Asset record, an identifying code, the size (in square feet), the monthly rent, and the amount of the security deposit. It should also contain a Tenant Number to indicate which Tenant is occupying the Tenant Space. If no Tenant is occupying a Tenant Space, we will leave this field blank. Create a Card to view and edit this table, also create a List to look up into this table. Provide a standard way to get from each one to the other. Provide a way to view, add and edit all tenant spaces for each Fixed Asset (property) from the Fixed Asset Card. Also, add a way to look up, from the Tenant Card, a List of all of the Tenant Spaces that this Tenant is occupying. Add a new tab to the Fixed Asset Card called "Tenant Spaces". On this tab, place four FlowFields, showing the number of Tenant Spaces, the total size, the total deposits and the total monthly rent. These last two must only be counted if the tenant space is actually occupied. Create a report called "Property List" which will list all Fixed Assets (properties) and for each one, lists each Tenant Space, including the number, size, tenant, tenant name (or "unoccupied" if there is no tenant), monthly rent, and deposit. There should be totals for each Fixed Asset (and a grand total for all Fixed Assets), of the size, the monthly rent and the deposits. Since some Fixed Assets are not properties, do not print anything for a Fixed Asset that does not have any Tenant Spaces related to it. Also, allow the user to filter this report by Fixed Asset, Tenant, and size.

Part 2:

Limitations

All navigation keys, field names, and so on, will adhere to Navision Standards.

Part 3:

Estimate
Hours 0.5 1.0 0.1 0.2 1.8

Work Element Specification Programming Testing Documentation Total

Property Management

8-19

Part 4:

Impact on Upgrades

This Requirement will have minimal impact on upgrades. Only the Tenant Card and Fixed Asset Card changes (adding the FlowFields to the Fixed Asset table, and menu buttons and fields to the forms) effect the base application. We recommend that whenever an upgrade is received, this requirement be reimplemented using the Change Log for those three objects only. We estimate that this will take 0.3 hours per upgrade.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

8-20

Navision Attain Solution Development

7.4: Tenant Journal


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Create Tenant Journal to Enter Revenue Entries Approved you 1.8 $225.00 1 2 $288.00 $513.00

Part 1:
7.1.12.

Technical Specifications
Function

Allow the user to make Journal Entries for Tenant Revenue. This will be called the Tenant Journal. The user must be able to enter a Fixed Asset, Tenant Space and Date. The Tenant can be defaulted or entered, and the Amount is the Amount charged to the Tenant. There will be a way to automatically fill the journal with one or more properties. Fill the Journal with all the currently rented spaces, and the Monthly Rent as the amount. Allow the user to modify the entries before posting. This function should be called from the Journal.

7.1.13.

Value

This Journal will allow the user to make Revenue Entries for Tenant Spaces in an efficient manner consistent with Navision Standards.

7.1.14.
None.

Current Functionality

Property Management

8-21

7.1.15.

New Functionality

Create a Tenant Journal table in which charges to the Tenants are entered. The user must enter the Fixed Asset, the Tenant Space and the Date. The Tenant No. should be filled in automatically, but can be overridden (in case the Tenant to be charged has already moved out). There should be a single amount per line, the amount to be charged to the tenant. If the entered Date is the first of the month, default this amount to the Monthly Rent for that Tenant Space. Allow for a standard length description. Whenever a new line is added, the Fixed Asset and the Date should be copied from the line above. There is only one Journal, so there is no need for any Journal Templates or Batches. Create a worksheet window in which the user can make Tenant Journal entries. A batch job (a processing only report) should be created which will automatically create entries into this journal for us. It should ask the user for a Posting Date on the Option tab of the Request Form and make sure that this date is on the first of a month. It should then run through all Tenant Spaces that have a Tenant, filling in the journal with the information on that Tenant Space record, including the Monthly Rent as the amount. The description should be set to the name of the Posting Date's month, followed by the word "Rent" (e.g. "January Rent" or "June Rent"). This report should allow us to filter the Tenant Spaces by Fixed Asset. We should be able to call it from the Tenant Journal by selecting a menu button there.

Part 2:

Limitations

Only one Journal is needed, so there will not be any Journal Templates or Journal Batches.

Part 3:

Estimate
Hours 0.5 1.0 0.1 0.2 1.8

Work Element Specification Programming Testing Documentation Total

8-22

Navision Attain Solution Development

Part 4:

Impact on Upgrades

None. These objects can be carried forward without change during an upgrade.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

Property Management

8-23

7.5: Tenant Space Ledger


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Standard Ledger and Transaction Report Specification in progress you

Part 1:
7.1.16.

Technical Specifications
Function

The entries entered into the Journal will be posted into a Ledger. This ledger can be viewed from the Tenant Space Card. The Ledger and Ledger Form will need to be created. Create a report that will show Ledger Entries per Tenant Space, including a total per Tenant Space, a total per Fixed Asset (property) and a Grand Total. Allow user to enter a Date Filter so this report can be from a particular Date Range. Add a FlowField to the FA Tenant Space Card (not the list), which shows the total transactions in the Ledger for this Tenant Space. Be sure to take the Date Filter into account.

7.1.17.

Value

Standard Transaction functionality. Allows user to view or print full detail of all transactions on a Tenant Space basis.

7.1.18.
None.

Current Functionality

8-24

Navision Attain Solution Development

7.1.19.

New Functionality

Complete this section

Part 2:

Limitations

No Registers will be created. Entries will not be allowed directly into the Ledger through the Ledger Entries form.

Part 3:

Estimate

Complete this section.


Work Element Specification Programming Testing Documentation Total Hours

Part 4:

Impact on Upgrades

Complete this section.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Property Management

8-25

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

8-26

Navision Attain Solution Development

7.6: Posting
Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: Post from Tenant Journal to Tenant Ledger Approved you 2.2 $275.00 0 4 $96.00 $371.00

Part 1:
7.1.20.

Technical Specifications
Function

The Tenant Journal must be able to be posted to the Tenant Space Ledger. It should also post to the General Ledger at the same time. The Debit goes to the Tenant and the Credit goes to the Revenue Account stored in the FA Posting Group. The Document Number is automatically generated using the Tenant Charges No. Series on the FA Setup.

7.1.21.

Value

Posting will be simple and will update both ledgers in one procedure.

7.1.22.
None.

Current Functionality

7.1.23.

New Functionality

Create a standard set of four codeunits to post the Tenant Journal. The first should be a Check Line codeunit. It should test if the line is empty (no Fixed Asset, No Tenant Space and no Amount), and if it is, nothing should happen for this line. It then should test to be sure that we entered a Tenant, a

Property Management

8-27

Fixed Asset, a Tenant Space, an amount and a Date, and that the date is not a Closing Date. The second should be a Post Line codeunit. It should check to see if the line is empty, and if it is, nothing should happen for this line. It should then call the Check Line codeunit. Then check to make sure that the Fixed Asset, the Tenant and the Tenant Space are all valid. It should create a Tenant Space Ledger entry for this journal line, copying the information and inserting the new entry. And it should post this information to the General Ledger as follows -

The debit (the amount in the journal) should be posted to the Tenant account. It should be balanced by a credit to the Revenue Account listed in the related Fixed Asset Posting Group. The description should be copied from the Tenant Journal. The Document Number (Doc Type = Invoice) should be generated from the Tenant Charges No. Series entered in the FA Setup table.
The third codeunit should be a Post Batch codeunit. It should run through the Tenant Journal (as the user has currently filtered it) and call the Check Line codeunit for each line. Then it should call the Post Line codeunit for each line. Finally, it should delete the lines. A dialog window showing the progress should be displayed while this is taking place. The fourth should simply ask if the user wants to post. If so, it should call the Post Batch codeunit. If not, it should simply exit, doing nothing. This codeunit should be called from the Tenant Journal when the user selects it from a menu button there.

Part 2:

Limitations

No Register is being created at this time. Payment of these charges is made through the normal procedures of the Basic Receivables granule. Dimensions will not be used. Any customers with Dimensions previously defined will need to delete those Dimensions for posting.

8-28

Navision Attain Solution Development

Part 3:

Estimate
Hours 0.6 1.2 0.2 0.2 2.2

Work Element Specification Programming Testing Documentation Total

Part 4:

Impact on Upgrades

None. These objects can be carried forward without change during an upgrade.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

Property Management

8-29

7.7: Data Conversion


Summary: Status: Assigned To: Hours Estimated: Estimated Labor: New Table Objects: Other New Objects: New Object Cost: Estimated Billing: 1 $24.00 Import Tenant Spaces Specification in progress you

Part 1:
7.1.24.

Technical Specifications
Function

A Tenant Space text file will be created by Spinner Enterprises. It will be a flat file, with fixed length fields, one Tenant Space per line. It must be imported into Navision Attain to initialize the Tenant Space table.

7.1.25.

Value

Will be able to bring in data from old systems quite rapidly.

7.1.26.
None.

Current Functionality

7.1.27.

New Functionality

Complete this section.

Part 2:

Limitations

Test file will be provided by the Spinner Enterprises.

8-30

Navision Attain Solution Development

Part 3:

Estimate

Complete this section.


Work Element Specification Programming Testing Documentation Total Hours

Part 4:

Impact on Upgrades

None. Once data conversion is complete, this dataport can be safely erased.

Part 5:

Approval

Customer has given us written approval on the Concept and has waived approval on all Design Specifications.

Part 6:
Object Type

Objects
Object Number Object Name Base Version (or "New")

Lab 9 The Upgrade Process

The exercises in this chapter will reinforce the knowledge that you have gained in this part of the course. If you have read and understood all of the material up to this point, you should be able to complete all of the exercises in this chapter. This chapter covers the following section: 9.1 Upgrading a Customized Database

9-2

Navision Attain Solution Development

9.1 Upgrading a Customized Database


In this section, you will upgrade a modified Navision Financials 2.60.B database to Navision Attain 3.01.A. Before the upgrade, read over the Property Management concept document to become familiar with the impact the modifications have on the database you will be upgrading. This document can be found in Lab 8.

9.1.1 Upgrading the Customized Database To perform this lab you will need to follow the instructions in the UpgradeToolkit-Instructions.PDF file. This file is the Upgrade Toolkit manual for Navision Attain 3.01. The custom database is called SpinnerEnterprises.FDB (it is version 2.60.B). If you need a clean 3.01.A database, use the one on the class disk. Remember to test the resulting database by posting in several areas including the Tenant Journal on the Fixed Asset menu.