Sie sind auf Seite 1von 103

Navision

A practical approach

Presentation
Flemming Mortensen. Navision since 1991. Partner in Logos Consult A/S, a Danish midsized Microsoft Partner specializing in Business Solution. Participated in development of parts of the standard application. Taught development in Navision 97 04.

Presentation
Logos Staff
4 programmers 4 consultants 2 salespersons 1 admin

Typical customer 5 to 50 users Database between 750 MB and 5 GB No IT-staff

Presentation
Typical project 50 to 500 hours 1, at most 2, programmers 1 consultant

Purpose
Show the practical use of Navision as development environment for administrative solutions. Argue its virtues Simple Safe

Scope
Classic Navision Native database Basic field and variable types Classic objects: Tabel Form Report Dataport Codeunit

Facts
Navison is a Client / Server based administrative solution. Small and exact pieces of data with a long life expectancy. The business logic is all made in C/Side, a development environment build for this purpose.

Design
Enforces few restrictions on work flow. Copies data freely to allow both use of defaults, e.g. a Unit Price and exceptions, e.g. a special Unit Price. Or to save copies of data with higher longevity than the original. Divided in Functional Areas of identical structure.

Functional Area
The Navision application consists of a number of Functional Areas. A Functional Area is a set of related business functionality.

Examples
Examples of Functional Areas: General Ledger Sales & Receivables Purchase & Payables Fixed Asset Inventory Resources Jobs

Only Functional Areas


There is very little functionality which isnt related to exactly one functional area. Comments Multi Dimensions And even less that isnt related to any. Users

Uniformity
All Functional Areas are build with the same few, welldefined components. The application is not made up of a random subset of all possible uses of C/Side.

The 4 Basic Components


The 4 main components of a Functional Area: Master Table
e.g. Table 27 Item

Journal Line Table


e.g. Table 83 Item Journal Line

Ledger Entry Table


e.g. Table 32 Item Ledger Entry

Posting Function
e.g. Codeunit 22 Item Jnl.-Post Line

The 4 Basic Components


Master Table

Jnl. Line Table

Ledger Entry Table

Posting Function

The 4 Basic Components


Item

Item Journal Line

Item Ledger Entry

Item Jnl.-Post Line

Reuse
The design of a functional area, specifically the Journal Line Posting Function Ledger Entry setup allows for a very high degree of reuse of code, and at a very high level.

Interfacing with a Func. Area

Master Table

Jnl. Line Table

Other Posting Function

Ledger Entry Table

Posting Function

Example Posting an Invoice


Sales & Receivables
Sales Header and Sales Lines

Inventory
Item Item Journal Line Codeunit 80

Item Ledger Entry

Codeunit 22

Post. Sales Invoice and Posted Inv. Lines

Posting
In Navision the term posting can have several more or less precise meanings: 1. Posting a journal or journal line. 2. Posting a document such as an sales order. 3. Activating some function to store data in an non editable format and in the process testing that the data is consistent. Below we first discuss posting journals and then documents in some detail.

Posting 1
Only codeunit 13 knows the entire journal. Both 11 and 12 are called with single journal line record variables. 13 11 12

Posting 2
13 passes each line to 11 for test. 13 passes each line to 12 for posting. 13 then deletes all lines.
13

11

12

Posting 3
13 is only one of many functions, that calls 12 to post a journal line. It is consequently not allowed to let 13 influence the posting by letting it mark one line with information from other lines or in any other way use its knowledge of the context. Thus its 12, which is responsible for creating the Register for each posting transaction even at the price of a performance penalty. This is contrary to what actually happens with Bill-to/Payto No. which is anyway a piece of crap.

Ledger Entries 1
All ledger entry tables have a field called Entry No., which is the sole field in the primary key. The Entry No. is assigned consecutively by the posting function. 1, 2, 3 The only exception are the customer and vendor ledger entries. They share the entry number series with the general ledger entries.

Ledger Entries 2
Sharing numbers:

Registers
All ledger entries from 1 posting transaction are grouped together by a register entry, holding the first and the last of the entry numbers.

Registers 2

Integration 1
Any module that creates a ledger entry must, ultimately, do it by creating a journal line variable and then post it with the corresponding 12-function. But this allows us to reuse all the functionality in the 12 function and often the trigger code on the journal line.

Integration 2
An important consequence of the posting design is that to post a journal line, the journal line record needs not to be written to the database. This makes the integration, from a technical point of view, very easy and robust.

Integration 3
Another, perhaps more high level, way to integrate a module with the standard application is to create a not posted document, e.g. an sales invoice, and then to post it with the corresponding document posting function, e.g. codeunit 80. Because documents consists of a header and several lines they must be written to the database before they can be posted. This makes it a bit more fragile and complicated than posting lines from within the code.

Posting Documents 1
But it is still facilitated by the detailed design of the document posting function.

81

80

Posting Documents 2
1. 81 is responsible for the dialog Do you want to post the invoice?. 2. 80 is responsible for the actual posting. 3. You can substitute 81 with 82 to get post and print. 4. There is also a post batch for documents report 297, which calls 80 for each document.

Posting Documents 3
1. It is the same set of tables, 36 / 37, which is used for the different types of not posted documents: Quote, Order, Invoice, Credit Memo, Blanket Order and Return Order. 2. The primary key of Table 36 is Document Type and Document No. Document Type is the field that makes the document to a quote, order, invoice etc. 3. It is always codeunit 80 which is used to post a document, whether its an invoice, an order, a credit memo or a return order.

Posting Documents 4
1. Contrary to the not posted documents, the posted documents are stored in different tables depending on type. 2. Posted Shipment Table 110 / 111 3. Posted Invoice Table 112 / 113 4. Posted Credit Memo Table 114 / 115

Posting Documents 5
1. When codeunit 80 posts an invoice, it creates a posted invoice header (Table 112) and a set of posted invoice lines (Table 113). And, depending on set up, a posted shipment header (Table 110) and a set of posted shipment lines (Table 111).

Posting Documents 6
36 / 37 Document Type = Invoice Depending on set up

Codeunit 80

110 / 111 Post. Sales Ship. and Lines

112 / 113 Post. Sales Invoice and Lines

Posting Documents 7
2. When codeunit 80 posts an order, it creates a posted invoice header (Table 112), a set of posted invoice lines (Table 113), a posted shipment header (Table 110) and a set of posted shipment lines (Table 111). The unique power of orders is their ability to be partially posted.

Posting Documents 8
36 / 37 Document Type = Order

Several sets when partial shipment or invoicing

Codeunit 80

110 / 111 Post. Sales Ship. and Lines

112 / 113 Post. Sales Invoice and Lines

Posting Documents 9
3. When codeunit 80 posts a credit memo, it creates a posted credit memo (Table 114) and set of posted credit memo lines (Table 115).

Posting Documents 10
36 / 37 Document Type = Cr. Memo

Codeunit 80

114 / 115 Post. Sales Cr. Memo and Lines

Posted Doc. & Ledg. Entries 1


When posting a document you get both a posted document Sales Invoice / Lines, and ledger entries.
36 / 37 Document Type = Invoice

Cust., G/L, Item, Res, Ledger Entries

Codeunit 80

112 / 113 Post. Sales Invoice and Lines

Posted Doc. & Ledg. Entries 2


Both the ledger entry tables and the posted document tables are of cause non editable. It is however possible to delete posted documents, basically as soon as they have been printed. Whereas ledger entries cannot be deleted unless a lot of conditions have been meet they must be old, etc., etc. And even then, they are not really deleted, but compressed. Therefore: Be careful about basing statistics, e.g. reports, on posted documents.

Posted Doc. & Ledg. Entries 3


Ledger entry tables and the posted document tables are even non editable in such a way, that they can only be edited with either: An object with explicit permissions to do so, e.g. the posting function. Or when a solution developer license (04) is used.

Dimensions 1
The purpose of dimensions is to link ledgers entries to, for example, a project or a department. To that end each ledger entry has 2 fields: Department Code and Project Code that can link each ledger entry to a department or a project. Just like the account number links it to an account. This is exactly how it was up to and including version 2.70.

Dimensions 2
An important feature in version 3.0 was the introduction of an infinite number of dimensions.

Dimensions 3
As we cannot have an infinite number of fields in a table, the new feature is implemented by the Ledger Entry Dimension table Table 355.

Dimensions 4
Ledger Entry Dimensions are of cause created by the posting function 12, based on the journal line dimensions. The journal line dimensions are much like the ledger entry dimensions, just for journal lines. Again its the same table, Table 356, which is used for all types of journals, g/l, item, resource etc.

Dimensions 5
Journal line dimensions can be entered by the user. They are also automatically created, when the number of a master table (e.g. G/L acc. No., Customer No., Item No.) is entered on the journal line. This happens because Navision then copies the Default Dimension of the master table record.

Dimensions 6
The old Department Code and Project Code have been kept as Global Dimension 1 and 2 on the ledger entry itself. And of cause as entry dimensions. Which of the many dimensions that are selected as global dimensions, is decided in G/L Setup.

Dimensions 7
The 8 Shortcut Dimensions are much as Global Dimensions, but for journals. The 2 first shortcut dimensions must be the same as the global dimensions. The last 6 shortcut dimensions are not stored as fields on the journal line tables. It only looks like it.

Dimensions 8
One reason for having the global dimensions is of cause backwards compatibility and general ease of use. But beyond that, note that there is a significant difference in the power of a global and a not global dimension. It is easy to find ledger entries with a specific global dim value, you just apply the filter It is difficult to find ledger entries with a specific non global dimension, you cannot just apply a filter. To overcome this we have Analysis View, but only for general ledger and inventory.

What is C/Side
C/Side Client / Server Integrated Development Environment. The development system for the business logic in Navision. Including the C/AL Client Application Language programming language

C/Side
C/Side is not a general purpose development environment. It is accessible to others than full time programmers. It is powerful enough to allow professional programmers to structure larger programs correctly.

C/Side
It is simple and easy to learn Few and simple concepts. Few uniform object types. Simple database interface. It is safe Version principle aka read consistency. Write Transactions.

Versions
A process works on a consistent snapshot of the database.

Transactions
A Write Transactions starts automatically when a process writes to the database. A write transaction is either completed successfully or aborted. A write transaction automatically ends, when the process ends and gives control back to the user. A write transaction can be ended inside code. Either with COMIT Or by encapsulating it inside a call to the default function of a codeunit. Write transactions do not nest.

C/Side
C/Side consists offers a few basic types of objects: Table Form Report Dataport Codeunit (XMLporte) (MenuSuite)

Tables
Table
Fields
Properties Triggers

Keys
Properties

Properties Triggers User defined functions


Parameters and return value Properties

Forms
Form
Controls
Properties Triggers

Properties Triggers User defined functions


Parameters and return value Properties

Reports
Report
Dataitem
Properties Triggers

User defined functions


Parameters and return value Properties

Sections
Controls Triggers Properties

Properties Triggers Optional Req. Form

Dataports
Dataport
Dataitem
Properties Triggers

User defined functions


Parameters and return value Properties

Dataport fields
Controls Triggers Properties

Properties Triggers Optional Req. Form

Codeunits
Codeunit
Default function
Limited parameters and return value Special semantic of return value

User defined functions


Parameters and return value Properties

C/AL
Basic control structure from Pascal IF THEN ELSE REPEAT UNTIL WHILE DO FOR TO WITH DO BEGIN END CASE OF := ; as statement separator

C/AL
Strongly typed. Variables are either Of a simple type or Of type some objects Functions Do not nest Have call by value and call by reference parameters Have simple return values Object variables must be passed as call by ref. to preserve their properties other than field values in records.

Variables
In C/AL there are Local and Global variables. Local and global variables are different in two ways: Scope and Lifetime.

Scope of Global variables


Global variables are global in the sense that they can be accessed from anywhere in the object where they have been declared. They cannot be accessed directly from other objects. Assume that we have 2 objects, e.g. 2 codeunits. They can both have a variable Cust. The two Cust variables will then be distinct entities.

Cust

Cust

Scope of Variables
The scope of a local variable is the trigger or the function in which is has been declared.
Cust

F Cust

G Cust

The Initial Value of a Variable


When a process for the first time accesses a variable it will automatically be initialised. Decimals and Integers will for example be 0 (zero). In a record variable the fields will have their respective default value if used the InitValue property of each field will be used.

The Lifetime of a Variable


Global variables are only initialised the first time a process accesses the variable. Local variables are initialised each time a process calls the function or trigger in which it is declared.

Temporary Tables
C/AL doesnt have pointers. The need for dynamically created variables is covered by temporary tables. Temporary tables are ordinary record variables with the property Temporay set to yes. This create a private table for this specific instance of the record variable. But with all the ordinary features of the table, including access by the well know database functions. Writing to a temporary table doesnt trigger a write transaction.

Signature Examples 0
A signature example from c
while(*t++ = *s++);

Signature Examples 1.1


To delete related records code is added to the OnDelete trigger of a table.
OnDelete() StdCustSalesCode.SETRANGE("Customer No.","No."); StdCustSalesCode.DELETEALL(TRUE);

Signature Examples 1.2


C/AL is variable-focused. This will not work:

OnDelete() StdCustSalesCode.SETRANGE("Customer No.","No."); StdCustSalesCode2.DELETEALL(TRUE);

Signature Examples 2.1


To loop through a table:
IF Cust.FIND(-) THEN REPEAT // Some action on Cust UNTIL Cust.NEXT = 0;

Signature Examples 2.2


A more complete example:
Cust.SETCURRENTKEY(Country Code); Cust.SETRANGE(Country Code,DK); IF Cust.FIND(-) THEN REPEAT Cust.Post Code := DK- + Cust.Post Code; Cust.MODIFY; UNTIL Cust.NEXT = 0;

Signature Examples 2.3


And something that doesnt work:
Cust.SETCURRENTKEY(Country Code); Cust.SETRANGE(Country Code,); IF Cust.FIND(-) THEN REPEAT Cust.Post Code := DK- + Cust.Post Code; Cust.Country Code := DK; Cust.MODIFY; UNTIL Cust.NEXT = 0;

Signature Examples 2.4


And the fix:
Cust.SETCURRENTKEY(Country Code); Cust.SETRANGE(Country Code,); IF Cust.FIND(-) THEN REPEAT Cust2 := Cust; Cust2.Post Code := DK- + Cust.Post Code; Cust2.Country Code := DK; Cust2.MODIFY; UNTIL Cust.NEXT = 0;

Signature Examples 3.1


Fragments of a posting function (13):
IF NOT FIND(=><) THEN EXIT; StartLineNo := "Line No."; REPEAT CarJnlCheckLine.RunCheck(CarJnlLine); IF NEXT = 0 THEN FIND('-'); UNTIL "Line No." = StartLineNo; FIND('-'); REPEAT CarJnlPostLine.RunWithoutCheck(CarJnlLine); UNTIL NEXT = 0;

Signature Examples 3.2


Fragments of a posting function (12):
WITH CarJnlLine DO BEGIN IF NextEntryNo = 0 THEN BEGIN CarLedgEntry.LOCKTABLE; IF CarLedgEntry.FIND('+') THEN NextEntryNo := CarLedgEntry."Entry No." + 1 ELSE NextEntryNo := 1; END; CarLedgEntry.INIT; // Assignments CarLedgEntry."Entry No." := NextEntryNo; CarLedgEntry.INSERT; NextEntryNo := NextEntryNo + 1; END;

Making Changes
A good modification is: Generally Navision Like. Supporting and using standard functionality. Easy to upgrade.

Upgrading with Changes


All objects and all fields have a unique number within the object type or table. Numbered entities are easy to merge.

Number 0 - 9,999 10,000 - 49,999 50,000 - 99,999 100,000 ..

Owner W1 Localization Partner Add on

Upgrading with Changes


Everything else must be merged by hand. Which isnt as difficult as people normally assume. You just have to exercise a minimum of care.

Handling Objects
Development Versions Documentation

Handling Objects
For each customer we have A common development database on M: A common folder with all object files P:\CustName\Objects An object log in our Navision. Customer, Object Log

Handling Objects
Example

Development Database
The common development database contains The current versions of the objects at the customer. Data that enables us to test special features. As a rule not the customers real data. It is named as <CustName_C/SideVersion>.fdb

The Development Cycle


Copy the database from M: to local computer Develop and test modifications Apply new version list to changed and new objects. Export them in an object file. Import the object file in the development database and copy it to the object folder. Register the object file in the object log Send the object file to the customer.

The Development Cycle


Store
Import objects

Development base

1. Copy database

Local database

2. Export objects

Development

Versioning
Versioning is the process of changing the fields Modified, Versionlist, Date and Time in the Object Designer. Versioning has 2 purposes: To make it easy to identify modified objects. To make it easy and safe for the customer to import the changed objects. Versioning expresses only chronology. There must never be a checkmark in Modified in a completed, versioned object.

Versioning
The customer must be able to import his objects with a dialog like this:

Versioning
Filter on Modified all objects that have been changed.

Versioning
Locate the customer in Navision. Open the Object Log. Find the next version no.

Versioning
For each object add the new version no. Apply uniform date and time. Remove checkmark in Modified

Versioning
Filter on all changed objects (*LC01.22) and export them to LC0122.FOB in the object folder Insert a line in the object log. Import the object file in the development database Send the object file to the customer

Versioning
Versioning is the fist step in documentation.

Documentation
Changes in a object, fields, keys, code, controls etc. are documented in the Documentation trigger of the object with the following syntax:
No. Version no. Initials Date - Description 01 LC01.22 FM 05.11.02 Field 50000 .. 50005 02 LC01.27 FM 27.04.05 New key: Country Code,Post Code

Documentation
Changes in code is also documented in the code:
// >> No.Initials Code // <<

DtldCVLedgEntryBuf."Initial Document Type" := "Document Type"; // >> 07.FM DtldCVLedgEntryBuf."Document Date" := "Document Date"; DtldCVLedgEntryBuf."Job No." := "Job No."; // << TransferCustLedgEntry(CVLedgEntryBuf,CustLedgEntry,TRUE);

Documentation
Variables are added at the bottom of the form, starting with a dummy variable >> LC Parameters are described in comments at the top of the function.

Documentation
Functions are added at the bottom of the form, starting with a dummy function >> LC F

Documentation
Text Constants are added at the bottom of the form, starting with a dummy constant >> LC C In so far that we are using the default naming conventions, we start with Text50000.

Upgrade
Respecting the above, we can offer our customers to upgrade their solution once a year for 10% of the original cost + minor fee per client. And make a business out of it.

Modifications
A modification is very customer specific, with a low degree of reusability. Customers, even in the same line of business, are not very similar. The standard application contains by definition the functionality which can be widely used. The partners ability to make changes allows the standard application to remain just that.

Table Triggers
All table triggers are on before triggers.
Trigger OnInsert OnDelete OnModify OnRename Databasefunction r.insert(true) r.delete(true) r.deleteall(true) r.modify(true) r.modifyall(..,true) r.rename(..)

Field Triggers
Trigger
OnValidate OnLookUp

Access from c/al


r.(field,value) n/a

Das könnte Ihnen auch gefallen