change nav 1-patterns formatting

This commit is contained in:
christianbraeunlich 2021-12-05 19:02:27 +01:00
parent ba12637e35
commit 7e4e21d223
54 changed files with 211 additions and 250 deletions

View file

@ -2,8 +2,6 @@
title = "Argument Table" title = "Argument Table"
weight = 220 weight = 220
+++ +++
## Argument table pattern
_Originally By Nikola Kukrika and waldo_ _Originally By Nikola Kukrika and waldo_
### Abstract ### Abstract

View file

@ -90,16 +90,13 @@ Entities where the Blocked Entity has been implemented include:
The [Released Entity][anchor4]. The [Released Entity][anchor4].
[watch?v=O2R fTSup1o&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=16][anchor5] {{< youtube O2R-fTSup1o >}}
[anchor0]: 2260.BlockedEntityPattern.png [anchor0]: 2260.BlockedEntityPattern.png
[anchor1]: /nav/w/designpatterns/247.data-driven-blocked-entity/edit [anchor1]: /nav/w/designpatterns/247.data-driven-blocked-entity/edit
[anchor2]: 8637.BlockedEntityPattern_5F00_5F00_5F00_Boolean.png [anchor2]: 8637.BlockedEntityPattern_5F00_5F00_5F00_Boolean.png
[anchor3]: 3056.BlockedEntityPattern_5F00_5F00_5F00_Option.png [anchor3]: 3056.BlockedEntityPattern_5F00_5F00_5F00_Option.png
[anchor4]: /nav/w/designpatterns/115.released-entity.aspx [anchor4]: /nav/w/designpatterns/115.released-entity.aspx
[anchor5]: https://www.youtube.com/watch?v=O2R-fTSup1o&list=PLhZ3P-LY7CqmVszuvtJLujFyHpsVN0U_w&index=16
[image0]: 2260.BlockedEntityPattern.png [image0]: 2260.BlockedEntityPattern.png

View file

@ -100,7 +100,7 @@ In the standard version of Microsoft Dynamics NAV, the Copy Document functionali
3. Copy Service Document (REP5979) 3. Copy Service Document (REP5979)
4. Copy Assembly Document (REP901) 4. Copy Assembly Document (REP901)
[watch?v=aTiwroXwW0&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=17][anchor5] {{< youtube aTiwroXwW0 >}}

View file

@ -189,7 +189,7 @@ Implement the solution in the standard version of Microsoft Dynamics NAV and ext
It is possible that users end up with a large number of templates if they need many different data combinations. An improvement could be to split templates into smaller groups, grouping only part of the fields that are related, and then apply only these. It is possible that users end up with a large number of templates if they need many different data combinations. An improvement could be to split templates into smaller groups, grouping only part of the fields that are related, and then apply only these.
[watch?v=F0CTvoyKSmI&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=20][anchor6] {{< youtube F0CTvoyKSmI >}}

View file

@ -2,7 +2,7 @@
title = "Currently Active Record" title = "Currently Active Record"
weight = 450 weight = 450
+++ +++
Authors: Henrik Langbak and Kim Ginnerup, Bording Data _Authors: Henrik Langbak and Kim Ginnerup, Bording Data_
## Abstract ## Abstract
@ -65,7 +65,9 @@ Remember to set the link table property before you save it.
### 3. Implement the code ### 3. Implement the code
```al
IF PriceView.FINDSET THEN // You have them IF PriceView.FINDSET THEN // You have them
```
### 4. Create a deployment codeunit ### 4. Create a deployment codeunit
@ -86,8 +88,8 @@ You need to deploy in three steps:
If you later want to change the view, you need to follow these rules: If you later want to change the view, you need to follow these rules:
\* If you add columns, you need to add them to the view first and then add them to the Table Object. * If you add columns, you need to add them to the view first and then add them to the Table Object.
\* If you want to remove columns from the view, you need to delete the Table Object, then change the view and last recreate the Table Object without the new columns. * If you want to remove columns from the view, you need to delete the Table Object, then change the view and last recreate the Table Object without the new columns.
### Code example that accomplish the same but without using the pattern ### Code example that accomplish the same but without using the pattern

View file

@ -1,9 +1,7 @@
+++ +++
title = "Data Migration Facade" title = "Data Migration Façade"
weight = 480 weight = 480
+++ +++
# **Data Migration Façade**
_By David Bastide and Soumya Dutta at Microsoft Development Center Copenhagen_ _By David Bastide and Soumya Dutta at Microsoft Development Center Copenhagen_
[![ ][image0]][anchor0] [![ ][image0]][anchor0]
@ -139,10 +137,8 @@ The overall workflow is:
* From the event subscribers, call the façade procedures to create entities and set their field values: * From the event subscribers, call the façade procedures to create entities and set their field values:
* * **"Item Data Migration Façade".CreateItemIfNeeded('ITEM042','My Item Description';'My Item Description 2';ItemTypeToSet::Inventory)** * * **"Item Data Migration Façade".CreateItemIfNeeded('ITEM042','My Item Description';'My Item Description 2';ItemTypeToSet::Inventory)**
* * **"Item Data Migration Façade".SetBaseUnitOfMeasure('BOX')**
**"Item Data Migration Façade".SetBaseUnitOfMeasure('BOX')** * **"Item Data Migration Façade".ModifyItem(true)**
*
**"Item Data Migration Façade".ModifyItem(true)**
[![ ][image2]][anchor2] [![ ][image2]][anchor2]
@ -267,7 +263,7 @@ The following Entity data migration façade codeunits are available:
## References: ## References:
Façade pattern on Wikipedia: https://en.wikipedia.org/wiki/Facade\_pattern Façade pattern on Wikipedia: https://en.wikipedia.org/wiki/Facade_pattern

View file

@ -2,7 +2,7 @@
title = "Discovery Event" title = "Discovery Event"
weight = 500 weight = 500
+++ +++
by waldo _by waldo_
# Abstract # Abstract

View file

@ -74,7 +74,7 @@ Save our page and add it to the Role Page "Order Processor Role Center" for exam
Now, observe how "Line No." is calculated on the first line, and when inserting a new line between the first and second one. Now, observe how "Line No." is calculated on the first line, and when inserting a new line between the first and second one.
Code sample (copy link to your browser) : https://knk1fr-my.sharepoint.com/personal/xgaronnat\_knk\_fr/\_layouts/15/guestaccess.aspx?guestaccesstoken=hL0P%2fyQ1ZreY5KlSPc%2b8dHrO4zjUkqQbg8DnGSbgd1Y%3d&docid=02b3cb93e1ff1459380891795fb8441fc Code sample (copy link to your browser) : https://knk1fr-my.sharepoint.com/personal/xgaronnat_knk_fr/_layouts/15/guestaccess.aspx?guestaccesstoken=hL0P%2fyQ1ZreY5KlSPc%2b8dHrO4zjUkqQbg8DnGSbgd1Y%3d&docid=02b3cb93e1ff1459380891795fb8441fc
## NAV Usages ## NAV Usages
@ -98,7 +98,7 @@ Use Series No. Pattern for your documents, and Copy Document to implement docume
## References ## References
Walkthrough: Creating a Document Page : [http://msdn.microsoft.com/en-us/library/dd338599(v=nav.71).aspx][anchor2] Walkthrough: Creating a Document Page : [http://msdn.microsoft.com/en-us/library/dd338599(v=nav.71).aspx][anchor2]
[][anchor2][watch?v=S9cRD2D4c0&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=27][anchor3] {{< youtube S9cRD2D4c0>}}

View file

@ -17,7 +17,7 @@ To guide users, we can prompt them with a dialog on which they can update the se
Define two functions in the setup or supplementary table: One for verifying if the needed information is available, and another for exposing the page that contains the fields that the user must update. Define two functions in the setup or supplementary table: One for verifying if the needed information is available, and another for exposing the page that contains the fields that the user must update.
Call the code. For example: Call the code. For example:
```AL
Local IsXAvailable : Boolean Local IsXAvailable : Boolean
If field X <\> '' then If field X <\> '' then
Exit(True) Exit(True)
@ -39,7 +39,7 @@ The calling code
SetupTable.VerifyAndSetX SetupTable.VerifyAndSetX
.. ..
```
## NAV Specific Example ## NAV Specific Example
**** ****
@ -53,10 +53,11 @@ Procedure VerifyAndSetOIOUBLPath(...)
The code in the **Sales & Receivables Setup** table can now be called directly from the related processing codeunit, such as the **Sales-Post + Print** codeunit (82). The code in the **Sales & Receivables Setup** table can now be called directly from the related processing codeunit, such as the **Sales-Post + Print** codeunit (82).
Were the code is called: Were the code is called:
```AL
IF ("EAN No." <\> '') THEN IF ("EAN No." <\> '') THEN
SalesSetup.VerifyAndSetOIOUBLPathSetup(SalesHeader."Document Type"); SalesSetup.VerifyAndSetOIOUBLPathSetup(SalesHeader."Document Type");
```
If the setup is not updated properly, the user is prompted to update it as follows. If the setup is not updated properly, the user is prompted to update it as follows.
@ -82,7 +83,7 @@ The anti-pattern is to do a testfield on a field that is not in the table that y
The test field message can often be confusing because the pages are often named differently than the tables, which can lead to misunderstanding and context-switching. The test field message can often be confusing because the pages are often named differently than the tables, which can lead to misunderstanding and context-switching.
[watch?v=oeASJN zqTo&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=18][anchor2] {{< youtube oeASJN-zqTo>}}

View file

@ -14,8 +14,8 @@ Missing, invalid or incomplete data is a common issue during data processing in
This article describes how to use the Error Message component in NAV, which in short gives you the possibility to: This article describes how to use the Error Message component in NAV, which in short gives you the possibility to:
1\. Link an error message to the page which enables you to resolve the problem. 1. Link an error message to the page which enables you to resolve the problem.
2\. Assemble all error messages in one central view instead of having to encounter them one by one. 2. Assemble all error messages in one central view instead of having to encounter them one by one.
Validating data is a common task during data processing in NAV. Unfortunately, validation is often done using NAV's integrated ERROR and TESTFIELD functions, which halt execution of the process. The user will then have to locate the invalid / missing data, correct it and reinitiate the process, possibly running into the next error, making the cycle repeat itself. This can be a very tedious, time-consuming and frustrating process. The error message component aims at improving this experience by providing a lightweight framework for error message logging and this article will explain how to leverage this functionality in your code. By doing so, all error messages are gathered during (pre-)processing and are finally presented to the user. The user then has the possibility to click on the error message, which will open the record where the invalid / missing data is located, thereby enabling the user to correct all mistakes efficiently, from one central place and in one go. Validating data is a common task during data processing in NAV. Unfortunately, validation is often done using NAV's integrated ERROR and TESTFIELD functions, which halt execution of the process. The user will then have to locate the invalid / missing data, correct it and reinitiate the process, possibly running into the next error, making the cycle repeat itself. This can be a very tedious, time-consuming and frustrating process. The error message component aims at improving this experience by providing a lightweight framework for error message logging and this article will explain how to leverage this functionality in your code. By doing so, all error messages are gathered during (pre-)processing and are finally presented to the user. The user then has the possibility to click on the error message, which will open the record where the invalid / missing data is located, thereby enabling the user to correct all mistakes efficiently, from one central place and in one go.
@ -31,13 +31,13 @@ By clicking on the error message, the user will be presented with the entity, wh
In the processing function, define a temporary record of type "Error Message". Use the functions on that record to populate the record with error message, a few of them being: In the processing function, define a temporary record of type "Error Message". Use the functions on that record to populate the record with error message, a few of them being:
* **LogIfEmpty****** * **LogIfEmpty**
* **LogIfLengthExceeded****** * **LogIfLengthExceeded**
* **LogIfInvalidCharacters****** * **LogIfInvalidCharacters**
* **LogIfOutsideRange****** * **LogIfOutsideRange**
* **LogIfGreaterThan****** * **LogIfGreaterThan**
* **LogIfEqualTo****** * **LogIfEqualTo**
* **LogMessage****** * **LogMessage**
The following parameters must be provided to these functions: The following parameters must be provided to these functions:
@ -52,17 +52,18 @@ When the processing is complete, you can check if any error messages of type "Er
The code below is an example of how the error message component was used in one part of the before mentioned Mexican feature. This code iterates over all G/L Accounts and pipes information out into an XML file. While doing so, it is validated that all mandatory fields have values and meet certain conditions. And only if that is the case, is the XML document actually exported. Also notice, that an error message is logged, in case no G/L Accounts are found given the provided filters. That way, the user can be guided to setup the system correctly. The code below is an example of how the error message component was used in one part of the before mentioned Mexican feature. This code iterates over all G/L Accounts and pipes information out into an XML file. While doing so, it is validated that all mandatory fields have values and meet certain conditions. And only if that is the case, is the XML document actually exported. Also notice, that an error message is logged, in case no G/L Accounts are found given the provided filters. That way, the user can be guided to setup the system correctly.
```AL
PROCEDURE ExportChartOfAccounts@1(Year@1000 : Integer;Month@1001 : Integer); PROCEDURE ExportChartOfAccounts@1(Year@1000 : Integer;Month@1001 : Integer);
VAR VAR
**TempErrorMessage@1003 : TEMPORARY Record 700; TempErrorMessage@1003 : TEMPORARY Record 700;
**BEGIN BEGIN
**TempErrorMessage.ClearLog;** // only necessary if variable is global TempErrorMessage.ClearLog; // only necessary if variable is global
... ...
CreateXMLHeader(Document,RootNode,CatalogoNodeTxt,Namespace,Year,Month,'1.1'); CreateXMLHeader(Document,RootNode,CatalogoNodeTxt,Namespace,Year,Month,'1.1');
IF GLAccount.FINDSET THEN BEGIN IF GLAccount.FINDSET THEN BEGIN
REPEAT REPEAT
**TempErrorMessage.LogIfEmpty (GLAccount,GLAccount.FIELDNO(Name),TempErrorMessage."Message Type"::Error); TempErrorMessage.LogIfEmpty (GLAccount,GLAccount.FIELDNO(Name),TempErrorMessage."Message Type"::Error);
**
XMLDOMManagement.AddElement(RootNode,'Ctas','',Namespace,Node); XMLDOMManagement.AddElement(RootNode,'Ctas','',Namespace,Node);
XMLDOMManagement.AddAttribute(Node,'CodAgrup',GLAccount."SAT Account Code"); XMLDOMManagement.AddAttribute(Node,'CodAgrup',GLAccount."SAT Account Code");
... ...
@ -72,18 +73,19 @@ The code below is an example of how the error message component was used in one
GLAccount."Debit/Credit"::Credit: GLAccount."Debit/Credit"::Credit:
XMLDOMManagement.AddAttribute(Node,'Natur','A'); XMLDOMManagement.AddAttribute(Node,'Natur','A');
ELSE ELSE
**TempErrorMessage.LogMessage( TempErrorMessage.LogMessage(
GLAccount,GLAccount.FIELDNO("Debit/Credit"),TempErrorMessage."Message Type"::Error, GLAccount,GLAccount.FIELDNO("Debit/Credit"),TempErrorMessage."Message Type"::Error,
STRSUBSTNO(GLAccountTypeErr,GLAccount."Debit/Credit",GLAccount.RECORDID)); STRSUBSTNO(GLAccountTypeErr,GLAccount."Debit/Credit",GLAccount.RECORDID));
** END; END;
UNTIL GLAccount.NEXT = 0; UNTIL GLAccount.NEXT = 0;
END ELSE END ELSE
**TempErrorMessage.LogSimpleMessage(TempErrorMessage."Message Type"::Error,NoSATAccountDefinedErr); TempErrorMessage.LogSimpleMessage(TempErrorMessage."Message Type"::Error,NoSATAccountDefinedErr);
**
**IF NOT TempErrorMessage.HasErrors(TRUE) THEN IF NOT TempErrorMessage.HasErrors(TRUE) THEN
** SaveXMLToClient(Document,Year,Month,'CT'); SaveXMLToClient(Document,Year,Month,'CT');
**TempErrorMessage.ShowErrorMessages(FALSE); TempErrorMessage.ShowErrorMessages(FALSE);
**END; END;
```
One could also do pre-processing in a function of its own, and only if the pre-processing results in no error messages of type "Error" would the processing continue. One could also do pre-processing in a function of its own, and only if the pre-processing results in no error messages of type "Error" would the processing continue.

View file

@ -27,8 +27,7 @@ _
< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 10\]\> < --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 10\]\>
< \[endif\]--\> < \[endif\]--\>
_Figure 1: Qualifier, Payload and emphasized text. _Figure 1: Qualifier, Payload and emphasized text._
_
## Usage ## Usage
@ -149,11 +148,9 @@ To format headlines, you should use Codeunit 1439 Headline Management functions:
_Figure 2: Sequence diagram of headline usage_ _Figure 2: Sequence diagram of headline usage_
## ## Usages in NAV:
Usages in NAV:
* Essential Business Headlines extension_ * Essential Business Headlines extension
_
< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if supportAnnotations\]--\>< --\[endif\]--\>< --\[if gte mso 10\]\> < --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if gte mso 9\]\>< \[endif\]--\>< --\[if supportAnnotations\]--\>< --\[endif\]--\>< --\[if gte mso 10\]\>
< \[endif\]--\> < \[endif\]--\>

View file

@ -63,6 +63,7 @@ The key question is: Where to tap into this flow when using a local data structu
In W1, the codeunit simply outputs the same set of general journal lines that it receives as an input: In W1, the codeunit simply outputs the same set of general journal lines that it receives as an input:
```AL
OnRun(VAR Rec : Record "Gen. Journal Line") OnRun(VAR Rec : Record "Gen. Journal Line")
GenJnlLine.COPYFILTERS(Rec); GenJnlLine.COPYFILTERS(Rec);
@ -92,6 +93,7 @@ LOCAL CreateTempJnlLines(VAR FromGenJnlLine : Record "Gen. Journal Line";VAR Tem
// To fill TempGenJnlLine from the source identified by filters set on FromGenJnlLine // To fill TempGenJnlLine from the source identified by filters set on FromGenJnlLine
TempGenJnlLine := FromGenJnlLine; TempGenJnlLine := FromGenJnlLine;
```
In a country, such as Italy, the codeunit will have the following functions: In a country, such as Italy, the codeunit will have the following functions:
@ -103,6 +105,7 @@ In a country, such as Italy, the codeunit will have the following functions:
1. Outputs the temporary general journal lines that will be further processed and exported, exactly as in W1\. 1. Outputs the temporary general journal lines that will be further processed and exported, exactly as in W1\.
```AL
OnRun(VAR Rec : Record "Gen. Journal Line") OnRun(VAR Rec : Record "Gen. Journal Line")
GenJnlLine.COPYFILTERS(Rec); GenJnlLine.COPYFILTERS(Rec);
@ -222,6 +225,7 @@ Description := VendorBillLine.Description;
INSERT; INSERT;
END; END;
```
The derived local feature flow is as follows: The derived local feature flow is as follows:

View file

@ -8,7 +8,7 @@ _By Eric Wauters ([waldo][anchor0]), Partner-Ready-Software_
As a partner, adding new code to NAV means interfering with code shipped by Microsoft. Minimize your footprint of changes in Microsoft code, so that, when a new NAV version is shipped, you avoid conflicts and upgrade impact. The core NAV code is the "danger zone" - the less you touch it, the happier your upgrade will be. As a partner, adding new code to NAV means interfering with code shipped by Microsoft. Minimize your footprint of changes in Microsoft code, so that, when a new NAV version is shipped, you avoid conflicts and upgrade impact. The core NAV code is the "danger zone" - the less you touch it, the happier your upgrade will be.
Description ## Description
When doing development over years, by different developers with different mindsets, the standard codebase gets changed a lot, adding multiple lines of code, adding local and global variants, adding or changing keys, changing existing business logic, ... . In other terms, the standard text objects are being changed all over the place.. . When doing development over years, by different developers with different mindsets, the standard codebase gets changed a lot, adding multiple lines of code, adding local and global variants, adding or changing keys, changing existing business logic, ... . In other terms, the standard text objects are being changed all over the place.. .
@ -28,42 +28,42 @@ I recommend to use this concept on:
## Usage ## Usage
Step 1 - if it doesn't exist yet - you create your Hook Codeunit. As the name assumes .. this is always a codeunit. We apply the following rules to it: **Step 1** - if it doesn't exist yet - you create your Hook Codeunit. As the name assumes .. this is always a codeunit. We apply the following rules to it:
* One Hook always hooks into one object. Which basically means that I will only declare this new codeunit in one other object (which is its parent object) * One Hook always hooks into one object. Which basically means that I will only declare this new codeunit in one other object (which is its parent object)
* The naming convention is: "The\_Original\_Object\_Name Hook". Naming conventions are important, just to find your mapped object, and also to be able to group the Hooks. * The naming convention is: "The\_Original\_Object\_Name Hook". Naming conventions are important, just to find your mapped object, and also to be able to group the Hooks.
Step 2, you create the hook, which is basically a method (function) in your codeunit. The naming is important: **Step 2**, you create the hook, which is basically a method (function) in your codeunit. The naming is important:
* The naming of the hook should NOT describe what it is going to do (So, examples like "CheckMandatoryFields", "FillCustomFields" should not be used as a hook) * The naming of the hook should NOT describe what it is going to do (So, examples like "CheckMandatoryFields", "FillCustomFields" should not be used as a hook)
* The naming of the hook should describe WHERE the hook is placed, not what the hook will be doing (as nobody is able to look into the future .. :-)) * The naming of the hook should describe WHERE the hook is placed, not what the hook will be doing (as nobody is able to look into the future .. :-))
* To help with the naming, it is a good convention to use the "On"-prefix for these triggers. This way, it's very clear what are hooks, and what aren't.. * To help with the naming, it is a good convention to use the "On"-prefix for these triggers. This way, it's very clear what are hooks, and what aren't..
Step 3, it's time to hook it to its corresponding object and right place in the business logic of that object. You do this by declaring your codeunit as a global in your object, and using the created hook function on its place in the business logic. This way, these one-liners apply: **Step 3**, it's time to hook it to its corresponding object and right place in the business logic of that object. You do this by declaring your codeunit as a global in your object, and using the created hook function on its place in the business logic. This way, these one-liners apply:
* A Hook Codeunit is only used once in one object only (its corresponding object) * A Hook Codeunit is only used once in one object only (its corresponding object)
* A Hook (function) is used only once in that object. As a consequence, changing the parameters has no consequence: you only need to change one function-call * A Hook (function) is used only once in that object. As a consequence, changing the parameters has no consequence: you only need to change one function-call
* The codeunit is declared as a global. That exact global is the only custom declaration in the existing object .. Everything else is pushed to the hook-codeunit. * The codeunit is declared as a global. That exact global is the only custom declaration in the existing object .. Everything else is pushed to the hook-codeunit.
Step 4, implement your business logic in the hook. Do this in the most atomic way, as there is a good chance that this same hook is going to be used for other business logic as well. Best is to use a one-line-function-call to business logic, so that the Hook Function itself stays readable. **Step 4**, implement your business logic in the hook. Do this in the most atomic way, as there is a good chance that this same hook is going to be used for other business logic as well. Best is to use a one-line-function-call to business logic, so that the Hook Function itself stays readable.
## Example ## Example
Suppose, we want to add business logic just before posting a sales document. In that case, we have to look for the most relevant place, which is somewhere in the "Sales-Post" codeunit. So: Suppose, we want to add business logic just before posting a sales document. In that case, we have to look for the most relevant place, which is somewhere in the "Sales-Post" codeunit. So:
Step 1: create codeunit "Sales-Post Hook" **Step 1**: create codeunit "Sales-Post Hook"
[![ ][image0]][anchor1] [![ ][image0]][anchor1]
Step 2: create the hook function "OnBeforePostDocument" **Step 2**: create the hook function "OnBeforePostDocument"
[![ ][image1]][anchor2] [![ ][image1]][anchor2]
Step 3: declare a global in the "Sales-Post"-codeunit, called "SalesPostHook". Then, call the Hook Function that you created in Step 2 in the right place. **Step 3**: declare a global in the "Sales-Post"-codeunit, called "SalesPostHook". Then, call the Hook Function that you created in Step 2 in the right place.
[![ ][image2]][anchor3] [![ ][image2]][anchor3]
Step 4: implement the business logic, by calling out to a new function. And implement the test-codeunit. **Step 4**: implement the business logic, by calling out to a new function. And implement the test-codeunit.
[![ ][image3]][anchor4] [![ ][image3]][anchor4]

View file

@ -137,7 +137,7 @@ Other risks could be if Transfer Fields are used and data is being copied uninte
This is a new pattern not currently used in Microsoft Dynamics NAV. This is a new pattern not currently used in Microsoft Dynamics NAV.
## **Ideas for improvement ****** ## **Ideas for improvement**
The reason for doing it this way is that you now can reuse your code again and again with only creating the same link on other tables instead of building it from scratch each time reducing testing needed and improving the quality of the overall product. The reason for doing it this way is that you now can reuse your code again and again with only creating the same link on other tables instead of building it from scratch each time reducing testing needed and improving the quality of the overall product.

View file

@ -136,7 +136,7 @@ Provide the support for the invoking any Help topics (URL on the Help Server fro
Implement tooltips across the application and in all country versions. (Requires a run-time infrastructure system.) Implement tooltips across the application and in all country versions. (Requires a run-time infrastructure system.)
[watch?v=loobQ1TVO3o&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=14][anchor6] {{< youtube loobQ1TVO3o>}}

View file

@ -2,7 +2,7 @@
title = "Integration of Addresses" title = "Integration of Addresses"
weight = 680 weight = 680
+++ +++
[watch?v=60Wrx9N gfY&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=19][anchor0] {{< youtube 60Wrx9N-gfY>}}

View file

@ -118,6 +118,7 @@ Following the flow above, the code (in the SEPA Credit Transfer example) is as f
The public interface of this table contains simple functionality for adding/deleting errors and for interrogation on if any errors are associated with the current journal template and batch. The public interface of this table contains simple functionality for adding/deleting errors and for interrogation on if any errors are associated with the current journal template and batch.
```AL
CreateNew(GenJnlLine : Record "Gen. Journal Line";NewText : Text) CreateNew(GenJnlLine : Record "Gen. Journal Line";NewText : Text)
SetLineFilters(GenJnlLine); SetLineFilters(GenJnlLine);
@ -161,6 +162,7 @@ DeleteJnlBatchErrors(GenJnlLine : Record "Gen. Journal Line")
IF JnlBatchHasErrors(GenJnlLine) THEN IF JnlBatchHasErrors(GenJnlLine) THEN
DELETEALL; DELETEALL;
```
## NAV Usages ## NAV Usages

View file

@ -121,6 +121,7 @@ Some of the fields in the Gen. Journal Batch table are not editable. Instead, th
Lookup("Gen. Journal Template".Recurring WHERE (Name=FIELD(Journal Template Name))) Lookup("Gen. Journal Template".Recurring WHERE (Name=FIELD(Journal Template Name)))
Similarly, the Template Type field is a FlowField that gets its value from the parent table: Similarly, the Template Type field is a FlowField that gets its value from the parent table:
Lookup("Gen. Journal Template".Type WHERE (Name=FIELD(Journal Template Name))) Lookup("Gen. Journal Template".Type WHERE (Name=FIELD(Journal Template Name)))
@ -174,7 +175,7 @@ References
For cases when most of the journal data can be used later (like monthly electricity payments, for example), the user has the possibility to save the current transaction details for later use. See the related pattern, Standard Journal. For cases when most of the journal data can be used later (like monthly electricity payments, for example), the user has the possibility to save the current transaction details for later use. See the related pattern, Standard Journal.
[watch?v=xtsZ5beNdZg&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=12][anchor7] {{< youtube xtsZ5beNdZg>}}

View file

@ -2,7 +2,7 @@
title = "Master Data" title = "Master Data"
weight = 780 weight = 780
+++ +++
__By [Soren Klemmensen][anchor0], [_Partner-Ready-Software_ ][anchor1]& [360 Visibility][anchor2]__ _By [Soren Klemmensen][anchor0], [_Partner-Ready-Software_ ][anchor1] & [360 Visibility][anchor2]_
# Abstract # Abstract

View file

@ -2,7 +2,7 @@
title = "Multi-file Download" title = "Multi-file Download"
weight = 800 weight = 800
+++ +++
#### _By Martin Dam at Microsoft Development Center Copenhagen_ _By Martin Dam at Microsoft Development Center Copenhagen_
## Abstract ## Abstract

View file

@ -87,8 +87,7 @@ PAGE.RUN(PAGE::"Blanket Sales Order",Rec);
END; END;
### **NAV Usages**[ ### **NAV Usages**[ ][anchor3]
][anchor3]
Some of the NAV implementations of this pattern can be found in the following pages: Some of the NAV implementations of this pattern can be found in the following pages:

View file

@ -254,7 +254,7 @@ IF AssistEdit(xRec) THEN
CurrPage.UPDATE; CurrPage.UPDATE;
[watch?v=1lG9rYdmM4&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=8][anchor3] {{< youtube 1lG9rY_dmM4>}}

View file

@ -2,7 +2,7 @@
title = "In-context Notifications" title = "In-context Notifications"
weight = 640 weight = 640
+++ +++
___By Soumya Dutta at Microsoft Development Center Copenhagen_ _By Soumya Dutta at Microsoft Development Center Copenhagen_
## Context ## Context

View file

@ -2,11 +2,9 @@
title = "Notification Lifecycle Management Pattern" title = "Notification Lifecycle Management Pattern"
weight = 880 weight = 880
+++ +++
**Notification Lifecycle Management pattern** _By David Bastide at Microsoft Development Center Copenhagen_
_By David Bastide at Microsoft Development Center Copenhagen _ [![ ][image0]][anchor0]
[![ ][image0]][anchor0]
@ -132,7 +130,7 @@ The simple case is:
[![ ][image4]][anchor4] [![ ][image4]][anchor4]
_Figure 4: without additional context****_ _Figure 4: without additional context_
[![ ][image5]][anchor5] [![ ][image5]][anchor5]

View file

@ -2,7 +2,7 @@
title = "Observer" title = "Observer"
weight = 900 weight = 900
+++ +++
#### _By Nikolai L'Estrange, from TVision Technology Ltd. in the UK__ _By Nikolai L'Estrange, from TVision Technology Ltd. in the UK_
_ _
### Abstract ### Abstract

View file

@ -16,7 +16,7 @@ For a processing routine to behave correctly, it needs sometimes input of a user
2. There are extra fields on the processing table, that are used internally and act like parameters. These Fields get filled according to the selections that the user has made 2. There are extra fields on the processing table, that are used internally and act like parameters. These Fields get filled according to the selections that the user has made
3. The processing codeunit receives the processing table, and therefor also the parameters 3. The processing codeunit receives the processing table, and therefor also the parameters
**[![ ][image0]][anchor0]** [![ ][image0]][anchor0]
## Usage ## Usage
@ -65,7 +65,7 @@ On the other hand, as we are handling tables as being "classes" in many cases, i
I would like to add a pattern like "Using Argument tables" (as a sub-pattern for the facade-pattern). It somewhat is related to this way of handling parameters: using tablefields to pass a flexible amount of parameters to functions/codeunits. I would like to add a pattern like "Using Argument tables" (as a sub-pattern for the facade-pattern). It somewhat is related to this way of handling parameters: using tablefields to pass a flexible amount of parameters to functions/codeunits.
[watch?v=SxywT2XSpcI&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=7][anchor4] {{< youtube SxywT2XSpcI>}}

View file

@ -45,7 +45,7 @@ Running the query yields a single record per document. You can notice in the sec
One thing is to be noted: there is a limitation to how much information you can take out from the records. For example, if we need to extract more information than just the one we already have in the columns, then the following apply: adding one more column of **Method Type** = **None** will indeed show more information, but it _might_ affect the grouping. More details below. One thing is to be noted: there is a limitation to how much information you can take out from the records. For example, if we need to extract more information than just the one we already have in the columns, then the following apply: adding one more column of **Method Type** = **None** will indeed show more information, but it _might_ affect the grouping. More details below.
**The grouping is affected **for example****when the additional column is the **VAT Entry No**. In this case, this column brings up additional grouping criteria and one group for each entry number will end up being created. **The grouping is affected** for example when the additional column is the **VAT Entry No**. In this case, this column brings up additional grouping criteria and one group for each entry number will end up being created.
[![ ][image4]][anchor5] [![ ][image4]][anchor5]

View file

@ -1,9 +1,8 @@
+++ +++
title = "use Queries to Detect Duplicate Records" title = "Use Queries to Detect Duplicate Records"
weight = 1340 weight = 1340
+++ +++
_Originally by Abshishek Ghosh and Bogdan Sturzoiu at Microsoft Development Center Copenhagen** _Originally by Abshishek Ghosh and Bogdan Sturzoiu at Microsoft Development Center Copenhagen_
**_
## **Abstract** ## **Abstract**
@ -33,13 +32,13 @@ Before Dynamics NAV 2013, the only possibility was to iterate through the table
This code would involve setting filters on the **Customer** table as many times as there are records in the table. This is an expensive operation. This code would involve setting filters on the **Customer** table as many times as there are records in the table. This is an expensive operation.
Starting with Dynamics NAV 2013, we can use queries to create a more efficient implementation of the same logic.**** Starting with Dynamics NAV 2013, we can use queries to create a more efficient implementation of the same logic.
## **Usage** ## **Usage**
The solution involves that you create a query to return duplicates, and then invoke it from a method that would test the value of the query to identify if duplicates were found. The solution involves that you create a query to return duplicates, and then invoke it from a method that would test the value of the query to identify if duplicates were found.
**Step 1 ****--****Creating the Query** **Step 1** -- **Creating the Query**
* The query must be created with the table we want to search in as the dataitem. * The query must be created with the table we want to search in as the dataitem.
* The field we want to search for must be created as a grouped field. * The field we want to search for must be created as a grouped field.

View file

@ -2,7 +2,7 @@
title = "Use Queries to Replace Nested Loops" title = "Use Queries to Replace Nested Loops"
weight = 1350 weight = 1350
+++ +++
#### _Originally by Bogdan Sturzoiu, Microsoft Development Center Copenhagen_ _Originally by Bogdan Sturzoiu, Microsoft Development Center Copenhagen_
## **Abstract** ## **Abstract**
@ -28,7 +28,7 @@ The join operation has traditionally been done in C/AL by record looping. When N
[![ ][image0]][anchor0] [![ ][image0]][anchor0]
Figure 1\. The pattern elements _Figure 1\. The pattern elements_
### **Usage** ### **Usage**
@ -72,7 +72,7 @@ The classic C/AL approach is to:
END; END;
******Solution Using Query** **Solution Using Query**
The new query-based approach involves: The new query-based approach involves:

View file

@ -2,8 +2,7 @@
title = "Read-once Initialization and Validation" title = "Read-once Initialization and Validation"
weight = 970 weight = 970
+++ +++
_By Tim Grant** _By Tim Grant_
**_
## **Abstract** ## **Abstract**
@ -39,7 +38,7 @@ E.g. If there is a bespoke change, then this existing **GetGLSetup** can be call
[][anchor3][![ ][image4]][anchor4] [][anchor3][![ ][image4]][anchor4]
This means that by the time the code reaches the original **GetGLSetup** code requirement, this record is already in memory as the status flag is set to True, eliminating another check. For such Patterns the setup record should never be cleared, it should be called once globally, initiated and left in memory for future checks. It should **not** be declared locally at the same time, review your code for matching local variable usage before implementing this.**** This means that by the time the code reaches the original **GetGLSetup** code requirement, this record is already in memory as the status flag is set to True, eliminating another check. For such Patterns the setup record should never be cleared, it should be called once globally, initiated and left in memory for future checks. It should **not** be declared locally at the same time, review your code for matching local variable usage before implementing this.
**** ****
@ -47,8 +46,7 @@ This means that by the time the code reaches the original **GetGLSetup** code re
Merge **Singleton Table** with dynamic validation field meta configuration. This removes the coding of **TESTFIELD** to a central setup check. Merge **Singleton Table** with dynamic validation field meta configuration. This removes the coding of **TESTFIELD** to a central setup check.
Example with the **Sales & Receivables Setup**** Example with the **Sales & Receivables Setup**
**
[![ ][image5]][anchor5] [![ ][image5]][anchor5]

View file

@ -2,7 +2,7 @@
title = "Released Entity" title = "Released Entity"
weight = 1000 weight = 1000
+++ +++
Authors: Henrik Langbak and Kim Ginnerup, Bording Data _Authors: Henrik Langbak and Kim Ginnerup, Bording Data_
## **Abstract** ## **Abstract**
@ -53,7 +53,7 @@ The important and critical part of this pattern is that the whole application ne
## **Usage** ## **Usage**
## To use this pattern you need to create an Option Field named: "Release State" with at least the two states: Open, Released. To use this pattern you need to create an Option Field named: "Release State" with at least the two states: Open, Released.
### Automatic pending or release ### Automatic pending or release

View file

@ -1,9 +1,7 @@
+++ +++
title = "1-sensitive-data-encapsulation.md" title = "Sensitive Data Encapsulation"
weight = 120 weight = 120
+++ +++
## Sensitive Data Encapsulation
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
_ _
@ -72,7 +70,7 @@ _Figure 2 - Data access before and after **Sensitive** **Data** **Encapsulation.
* **Clarity:** when all sensitive data is encapsulated in one place, it is clear which is the information that needs to be protected. * **Clarity:** when all sensitive data is encapsulated in one place, it is clear which is the information that needs to be protected.
* **Simplicity:** easier to protect just a limited number of known resources when they are grouped. * **Simplicity:** easier to protect just a limited number of known resources when they are grouped.
* **Homogeneity: **the same protection can be applied to all data, since it is stored in the same place.**** * **Homogeneity: **the same protection can be applied to all data, since it is stored in the same place.
* **Separation of concerns:** treat each section of the computer program differently, by separating it and clearly addressing its own requirements and limitations. \[1\] * **Separation of concerns:** treat each section of the computer program differently, by separating it and clearly addressing its own requirements and limitations. \[1\]
* **Performance**: data protection techniques like **Access Control** and **Encryption** can now be applied only to the sensitive data (not to everything), which improves the performance of the system. * **Performance**: data protection techniques like **Access Control** and **Encryption** can now be applied only to the sensitive data (not to everything), which improves the performance of the system.

View file

@ -1,9 +1,7 @@
+++ +++
title = "2-data-encryption.md" title = "Data Encryption"
weight = 140 weight = 140
+++ +++
## Encryption
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
__ __
@ -38,9 +36,9 @@ _Figure 1- **Encryption** becomes easier after first applying [**Sensitive Data
Table 1- Encryption functionality in Dynamics NAV (found in codeunit 1266 Encryption Management) Table 1- Encryption functionality in Dynamics NAV (found in codeunit 1266 Encryption Management)
**Procedure****** **Procedure**
**Description****** **Description**
**EnableEncryption** **EnableEncryption**

View file

@ -1,9 +1,7 @@
+++ +++
title = "3-single-point-of-access.md" title = "Single Point of Access"
weight = 160 weight = 160
+++ +++
## Single Point of Access
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
_[![ ][image0]][anchor0] _[![ ][image0]][anchor0]
@ -45,7 +43,7 @@ This shows how pattern application is an iterative process, where one step follo
* **Knowledge reuse**: if a bug is found and fixed, there is just one place which needs to be repaired. Therefore, there is no risk that some of the usages would still be flawed by the same bug. For example: * **Knowledge reuse**: if a bug is found and fixed, there is just one place which needs to be repaired. Therefore, there is no risk that some of the usages would still be flawed by the same bug. For example:
* **Double encryption**: The **Single Point of Access** API already implements knowledge to avoid encryption of already encrypted strings. * **Double encryption**: The **Single Point of Access** API already implements knowledge to avoid encryption of already encrypted strings.
* **Multi-company**: The **Single Point of Access** API already implements knowledge for handling encryption in a multi-company setup. * **Multi-company**: The **Single Point of Access** API already implements knowledge for handling encryption in a multi-company setup.
* **Easy maintenance**:****a change in specification needs only one code update. * **Easy maintenance**: a change in specification needs only one code update.
**Consequences:** **Consequences:**

View file

@ -1,9 +1,7 @@
+++ +++
title = "4-masked-text.md" title = "Masked Text"
weight = 180 weight = 180
+++ +++
## Masked Text
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
_[![ ][image0]][anchor0] _[![ ][image0]][anchor0]

View file

@ -1,9 +1,7 @@
+++ +++
title = "5-ssl-in-nav.md" title = "SSL in NAV"
weight = 190 weight = 190
+++ +++
## SSL in NAV
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
_[![ ][image0]][anchor0] _[![ ][image0]][anchor0]
@ -17,7 +15,7 @@ __
**Forces:** **Forces:**
* **Insecure communication: **When the user enters a password, if unprotected, a network sniffer \[12\] could catch and read it. A sniffer is either a software program or hardware device which examine network traffic. Years ago, sniffers were tools used exclusively by professional network engineers, but nowadays, they are also popular with Internet hackers and people just curious about networking.****A****public Wi-Fi network could easily be eavesdropped by an unwanted actor. * **Insecure communication:** When the user enters a password, if unprotected, a network sniffer \[12\] could catch and read it. A sniffer is either a software program or hardware device which examine network traffic. Years ago, sniffers were tools used exclusively by professional network engineers, but nowadays, they are also popular with Internet hackers and people just curious about networking. A public Wi-Fi network could easily be eavesdropped by an unwanted actor.
By using data storage patterns like **Sensitive Data Encapsulation**, **Encryption, Single Point of Access** or **Azure Key Vault**, the sensitive data is preserved securely in the implementation of Dynamics NAV. But before it gets into a secure store, this data needs to be transmitted from the user, through a user interface, on a client-server connection and all the way to the database. Is the data safe while being transmitted? By using data storage patterns like **Sensitive Data Encapsulation**, **Encryption, Single Point of Access** or **Azure Key Vault**, the sensitive data is preserved securely in the implementation of Dynamics NAV. But before it gets into a secure store, this data needs to be transmitted from the user, through a user interface, on a client-server connection and all the way to the database. Is the data safe while being transmitted?
@ -31,9 +29,6 @@ Figure 1 shows data communication between the client (where the user enters data
_Figure 1 - Data transmission before (http://...) and after SSL encryption (https://...)._ _Figure 1 - Data transmission before (http://...) and after SSL encryption (https://...)._
_
_
**Usage**: the latest information about how to configure SSL for the web client in Dynamics NAV is found online at on MSDN at [https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx][anchor2]. **Usage**: the latest information about how to configure SSL for the web client in Dynamics NAV is found online at on MSDN at [https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx][anchor2].
**Benefits:** **Benefits:**

View file

@ -2,12 +2,9 @@
title = "Security" title = "Security"
weight = 1030 weight = 1030
+++ +++
## **Security patterns for NAV
**
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
### **** ## **Security patterns for NAV**
### **Problem statement** ### **Problem statement**

View file

@ -8,8 +8,7 @@ _By Jan Hoek at IDYN_
The Setup Specificity Fallback pattern allows users to efficiently define a potentially complex setup in terms of rules and exceptions to these rules, exceptions to the exceptions, etc. The Setup Specificity Fallback pattern allows users to efficiently define a potentially complex setup in terms of rules and exceptions to these rules, exceptions to the exceptions, etc.
## **Description ## **Description**
**
The pattern involves a setup table with a compound (i.e. consisting of more than one field) primary key, where each record in the table maps a combination of primary key values to a particular setup value. However, setting up and maintaining each and every combination could prove to be rather labour-intensive. The pattern involves a setup table with a compound (i.e. consisting of more than one field) primary key, where each record in the table maps a combination of primary key values to a particular setup value. However, setting up and maintaining each and every combination could prove to be rather labour-intensive.

View file

@ -2,13 +2,11 @@
title = "Singleton" title = "Singleton"
weight = 1090 weight = 1090
+++ +++
## Singleton
_By Bogdana Botez at Microsoft Development Center Copenhagen_ _By Bogdana Botez at Microsoft Development Center Copenhagen_
[![ ][image0]][anchor0] [![ ][image0]][anchor0]
**Context: **The pattern described in this article applies to Dynamics NAV only. For the general definition of the **Singleton** pattern, see for example [this link][anchor1].** **Context:** The pattern described in this article applies to Dynamics NAV only. For the general definition of the **Singleton** pattern, see for example [this link][anchor1].
**
**Problem**: As a C/AL developer, you need to coordinate action (through a codeunit) or store information (in a table) that is unique across the system. **Problem**: As a C/AL developer, you need to coordinate action (through a codeunit) or store information (in a table) that is unique across the system.

View file

@ -2,13 +2,10 @@
title = "Singleton Codeunit" title = "Singleton Codeunit"
weight = 1100 weight = 1100
+++ +++
## Singleton Codeunit _By Bogdana Botez at Microsoft Development Center Copenhagen_
_By Bogdana Botez at Microsoft Development Center Copenhagen [![ ][image0]][anchor0]
_
_[![ ][image0]][anchor0]
_
**Problem**: In some situations, global state needs to be preserved at runtime throughout a session. **Problem**: In some situations, global state needs to be preserved at runtime throughout a session.

View file

@ -87,7 +87,7 @@ The **Singleton Table** has two established applications in Dynamics NAV:
YouTube Video of NAV Singleton: YouTube Video of NAV Singleton:
[watch?v=aQPu s9FkYI&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=13][anchor3] {{< youtube aQPu-s9FkYI>}}

View file

@ -2,13 +2,10 @@
title = "Cue Table" title = "Cue Table"
weight = 440 weight = 440
+++ +++
## Cue Table _By Bogdana Botez at Microsoft Development Center Copenhagen_
_By Bogdana Botez at Microsoft Development Center Copenhagen [![ ][image0]][anchor0]
_
_[![ ][image0]][anchor0]
_
Cues are the second usual application of the [**Singleton Table**][anchor1] pattern in Dynamics NAV, after [**Setup Tables**][anchor2]. Cues are the second usual application of the [**Singleton Table**][anchor1] pattern in Dynamics NAV, after [**Setup Tables**][anchor2].
@ -22,8 +19,6 @@ The overview information consists of summed-up numbers, calculated from business
**Problem**: NAV stores data in tables. By definition, a table is a repetitive structure containing multiple lines, each line having a different piece of the information. But sometimes this repetitive information needs to be summed-up or otherwise synthetized, and presented as an overview. **Problem**: NAV stores data in tables. By definition, a table is a repetitive structure containing multiple lines, each line having a different piece of the information. But sometimes this repetitive information needs to be summed-up or otherwise synthetized, and presented as an overview.
**
**
**Solution:** Store overview information in a singleton table. **Solution:** Store overview information in a singleton table.
@ -37,14 +32,13 @@ There are two ways of calculating overview information in NAV.
* * The way to calculate the overview is too complex for flow fields, or * * The way to calculate the overview is too complex for flow fields, or
* The data needs to be pulled from an external system (like Dynamics CRM, QuickBooks or any external integration). * The data needs to be pulled from an external system (like Dynamics CRM, QuickBooks or any external integration).
** ****
**
The implementation of Cues is already described in detail on MSDN, in [Creating and Customizing Cues][anchor4] and in [Walkthrough: Creating a Cue Based on a FlowField][anchor5]. The implementation of Cues is already described in detail on MSDN, in [Creating and Customizing Cues][anchor4] and in [Walkthrough: Creating a Cue Based on a FlowField][anchor5].
**NAV Usages** **NAV Usages**
Table 1 - Cue tables in Dynamics NAV****shows some examples of singleton tables used for creating Cues. _Table 1 - Cue tables in Dynamics NAV_ shows some examples of singleton tables used for creating Cues.
Table ID Table ID

View file

@ -2,11 +2,9 @@
title = "Setup Table" title = "Setup Table"
weight = 1070 weight = 1070
+++ +++
## Setup Table
_By Abhishek Ghosh, at Microsoft Development Center Copenhagen_ _By Abhishek Ghosh, at Microsoft Development Center Copenhagen_
## [![ ][image0]][anchor0] [![ ][image0]][anchor0]
This is the first and most well-known of the two usual applications of the **Singleton Table** pattern in Dynamics NAV. This is the first and most well-known of the two usual applications of the **Singleton Table** pattern in Dynamics NAV.

View file

@ -52,7 +52,7 @@ When saving the journal lines, the Save as Standard Gen. Journal report (750) is
1. Standard General Journal 1. Standard General Journal
2. Standard Item Journal 2. Standard Item Journal
[watch?v=XeTKmO2Eqgw&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=21][anchor9] {{< youtube XeTKmO2Eqgw>}}

View file

@ -4,19 +4,19 @@ weight = 1190
+++ +++
_Originally by Abhishek Ghosh, at Microsoft Development Center Copenhagen_ _Originally by Abhishek Ghosh, at Microsoft Development Center Copenhagen_
Abstract ## Abstract
This pattern generates the data to be displayed dynamically by combing/processing several data sources. It then displays the resulting dataset without writing to the database. This pattern generates the data to be displayed dynamically by combing/processing several data sources. It then displays the resulting dataset without writing to the database.
[![ ][image0]][anchor0][][anchor1] [![ ][image0]][anchor0][][anchor1]
Description ## Description
While writing reports in NAV, we have the luxury of using a built-in iterator. So, once we define the dataitem and the ordering, the runtime takes care of the iteration. While writing reports in NAV, we have the luxury of using a built-in iterator. So, once we define the dataitem and the ordering, the runtime takes care of the iteration.
The iterator has one shortcoming: It can only run through records written into the database. There are situations, however, where we want to display temporary datasets created at runtime by processing data from different sources. That is where the Temporary Dataset Report pattern can be used. The iterator has one shortcoming: It can only run through records written into the database. There are situations, however, where we want to display temporary datasets created at runtime by processing data from different sources. That is where the Temporary Dataset Report pattern can be used.
Usage ## Usage
This pattern takes a two-step approach to displaying the data: This pattern takes a two-step approach to displaying the data:
@ -72,7 +72,7 @@ With the first approach, in the Integer-OnAfterGetRecord trigger, you must make
With the second approach, you must limit the number of times the report iterates through the Integer dataitem. The Number field in the Integer table will have a value of 1 in the first iteration and will increment automatically by 1 on every subsequent iteration. To ensure that the report iterates through the Integer dataitem "n" times, you must, therefore, filter the Integer dataitem on Number = 1..n. You must also move the temporary record variable to the next record in every iteration of the Integer-OnAfterGetRecord trigger. NOTE: This technique cannot be used if you use queries as the temporary data source, since queries do not (in NAV 2013) return the number of records. With the second approach, you must limit the number of times the report iterates through the Integer dataitem. The Number field in the Integer table will have a value of 1 in the first iteration and will increment automatically by 1 on every subsequent iteration. To ensure that the report iterates through the Integer dataitem "n" times, you must, therefore, filter the Integer dataitem on Number = 1..n. You must also move the temporary record variable to the next record in every iteration of the Integer-OnAfterGetRecord trigger. NOTE: This technique cannot be used if you use queries as the temporary data source, since queries do not (in NAV 2013) return the number of records.
Example ## Example
Goal: To print a report that lists all contacts that have open documents (both sales and purchase) and displays those documents in chronological order Goal: To print a report that lists all contacts that have open documents (both sales and purchase) and displays those documents in chronological order
@ -139,9 +139,8 @@ This is a commonly used pattern in several reports, such as:
* Report 206 -- Sales -- Invoice * Report 206 -- Sales -- Invoice
[watch?v=QHn5oEOJv0Q&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=10][anchor8] {{< youtube QHn5oEOJv0Q>}}
* *
[anchor0]: /cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/0250.Temporary-Dataset-Report-1.gif [anchor0]: /cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/0250.Temporary-Dataset-Report-1.gif
[anchor1]: /cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/8424.Temporary-Dataset-Report-1.gif [anchor1]: /cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/8424.Temporary-Dataset-Report-1.gif

View file

@ -153,7 +153,7 @@ The pattern can easily be extended to new sales and purchase documents. If the p
Platform support to be able to trigger full-page update from the lines. Support does exist today, but it is not programmatically controlled at design time. This means that it cannot be used in all cases. Platform support to be able to trigger full-page update from the lines. Support does exist today, but it is not programmatically controlled at design time. This means that it cannot be used in all cases.
[watch?v=U3noU WT8Xk&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=22][anchor12] {{< youtube U3noU-WT8Xk>}}

View file

@ -2,7 +2,7 @@
title = "Transfer Custom Fields" title = "Transfer Custom Fields"
weight = 1230 weight = 1230
+++ +++
[watch?v=cGaBqwfGCws&list=PLhZ3P LY7CqmVszuvtJLujFyHpsVN0Uw&index=9][anchor0] {{< youtube cGaBqwfGCws>}}

View file

@ -2,9 +2,7 @@
title = "Variant Facade" title = "Variant Facade"
weight = 1440 weight = 1440
+++ +++
# Variant Façade _By Nikola Kukrika, waldo and Gary Winter_
By Nikola Kukrika, waldo and Gary Winter
# Abstract # Abstract
@ -48,7 +46,7 @@ Problems arising from this way of implementing code are:
**Testing the code** is hard since the tests need to be replicated. **Testing the code** is hard since the tests need to be replicated.
**Constant cost of adding support for new tables **-- when the new record type needs to be supported, it has a constant cost. Adding a support for a new record will increase the Maintenance tax and it will make the code harder to understand and extend. **** **Constant cost of adding support for new tables** -- when the new record type needs to be supported, it has a constant cost. Adding a support for a new record will increase the Maintenance tax and it will make the code harder to understand and extend.
**Conclusion** - **If the functionality needs to be used for many records the approach of duplicating the functions should be avoided.** **Conclusion** - **If the functionality needs to be used for many records the approach of duplicating the functions should be avoided.**