deploy: 9e06f72056
This commit is contained in:
parent
de09820554
commit
e4f08bf9a7
187 changed files with 6620 additions and 6342 deletions
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Activity Logs :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600598 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600598></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/activity-log/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600598></script>
|
||||
<script src=/js/auto-complete.js?1644600598></script>
|
||||
<script src=/js/search.js?1644600598></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -341,12 +341,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600598></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600598></script>
|
||||
<script src=/js/featherlight.min.js?1644600598></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600598></script>
|
||||
<script src=/js/relearn.js?1644600598></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Argument Table :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600598 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600598></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/argument-table/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600598></script>
|
||||
<script src=/js/auto-complete.js?1644600598></script>
|
||||
<script src=/js/search.js?1644600598></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -308,8 +308,8 @@ ALGuidelines.Dev
|
|||
<p>New table</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL>TAB <span style=color:#ae81ff>50003</span> VAT Return Data
|
||||
<span style=color:#66d9ef>PROCEDURE</span> FillInVATReturnData@<span style=color:#ae81ff>1200001</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> VATReturnData@<span style=color:#ae81ff>1200000</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>50003</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><hr>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL>VATReturnData<span style=color:#f92672>.</span>INIT;
|
||||
|
||||
VATReturnData<span style=color:#f92672>.</span>INIT;
|
||||
VATReturnData<span style=color:#f92672>.</span>NumberOfCopies <span style=color:#f92672>:=</span> GetDefaultNumberOfCopies;
|
||||
VATReturnData<span style=color:#f92672>.</span>Uploaded <span style=color:#f92672>:=</span> FALSE;
|
||||
|
||||
|
|
@ -343,12 +343,12 @@ FillInVATReturnData<span style=color:#f92672>(</span>VATReturnData<span style=co
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600598></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600598></script>
|
||||
<script src=/js/featherlight.min.js?1644600598></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600598></script>
|
||||
<script src=/js/relearn.js?1644600598></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Data Driven Blocked Entity :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/blocked-entity/data-driven-blocked-entity/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -271,7 +271,7 @@ ALGuidelines.Dev
|
|||
<h2 id=problem>Problem</h2>
|
||||
<p>A NAV record can be used in a number of functionalities across the app. There are situations, however, when the administrator wants to restrict the consumption of such a record, as well as lift the restriction when it is no longer relevant.</p>
|
||||
<p>For example, a new customer record should not be used for posting documents until it is approved by the relevant approver.</p>
|
||||
<p>We could solve this by using the <a href=/nav/w/designpatterns/79.blocked-entity>Blocked Entity pattern</a>, but it requires database schema changes, which have an upgrade impact.</p>
|
||||
<p>We could solve this by using the <a href=/navpatterns/1-patterns/blocked-entity/>Blocked Entity pattern</a>, but it requires database schema changes, which have an upgrade impact.</p>
|
||||
<p>The blocked entity pattern involves:</p>
|
||||
<ol>
|
||||
<li>Adding a “blocked” status field on the record (either a Boolean or in the more advanced cases, an option field refining the usage).</li>
|
||||
|
|
@ -304,11 +304,10 @@ ALGuidelines.Dev
|
|||
<p>All the approval workflows include a response that restricts usage of a record, and then, at the end of an approval loop, a response that allows the usage again by lifting the restriction. See responses “Add record restriction” and “Remove record restriction” implemented in COD1521.<a href=https://microsoft.sharepoint.com/teams/DynamicsNAV/Wiki/Nav%20Wiki%20Documents/NAV%20App%20Patterns/NAV%20App%20Patterns%20for%20Review/Data-Driven%20Blocked%20Entity.docx#_msocom_2><br>
|
||||
</a></p>
|
||||
<p>The code behind the “Add record restriction” workflow response:</p>
|
||||
<pre><code>RecRef.GETTABLE(Variant);
|
||||
Workflow.GET(WorkflowStepInstance."Workflow Code");
|
||||
RecordRestrictionMgt.RestrictRecordUsage(RecRef.RECORDID,STRSUBSTNO(RestrictUsageDetailsTxt,Workflow.Code,Workflow.Description));
|
||||
</code></pre>
|
||||
<p>The code behind the “Remove record restriction” response:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL>RecRef<span style=color:#f92672>.</span>GETTABLE<span style=color:#f92672>(</span><span style=color:#66d9ef>Variant</span><span style=color:#f92672>)</span>;
|
||||
Workflow<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>WorkflowStepInstance<span style=color:#f92672>.</span>"Workflow Code"<span style=color:#f92672>)</span>;
|
||||
RecordRestrictionMgt<span style=color:#f92672>.</span>RestrictRecordUsage<span style=color:#f92672>(</span>RecRef<span style=color:#f92672>.</span><span style=color:#66d9ef>RECORDID</span>,STRSUBSTNO<span style=color:#f92672>(</span>RestrictUsageDetailsTxt,Workflow<span style=color:#f92672>.</span><span style=color:#66d9ef>Code</span>,Workflow<span style=color:#f92672>.</span>Description<span style=color:#f92672>))</span>;
|
||||
</code></pre></div><p>The code behind the “Remove record restriction” response:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL>RecRef<span style=color:#f92672>.</span>GETTABLE<span style=color:#f92672>(</span><span style=color:#66d9ef>Variant</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>CASE</span> RecRef<span style=color:#f92672>.</span>NUMBER <span style=color:#66d9ef>OF</span>
|
||||
<span style=color:#66d9ef>DATABASE</span>::"Approval Entry":
|
||||
|
|
@ -344,12 +343,12 @@ RecordRestrictionMgt.RestrictRecordUsage(RecRef.RECORDID,STRSUBSTNO(RestrictUsag
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/blocked-entity/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Blocked Entity :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/blocked-entity/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -279,7 +279,7 @@ ALGuidelines.Dev
|
|||
<p>The Blocked Entity is used when it is required to stop transactions for an entity (mostly master data), temporarily or permanently.</p>
|
||||
<p><a href=2260.BlockedEntityPattern.png><img src=2260.BlockedEntityPattern.png alt=" "></a></p>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>To block entities through metadata, read this pattern. To do the same thing through data, read <a href=/nav/w/designpatterns/247.data-driven-blocked-entity/edit>Data Driven Blocked Entity pattern</a>.</p>
|
||||
<p>To block entities through metadata, read this pattern. To do the same thing through data, read <a href=/navpatterns/1-patterns/blocked-entity/data-driven-blocked-entity/>Data Driven Blocked Entity pattern</a>.</p>
|
||||
<p>The business entity holds a state that controls if a given transaction is allowed. The state is used by the logic controlling transactions. The change of state could either be temporary or permanent.</p>
|
||||
<p>An example of a temporary halt is when a retail chain selling items has received lot of complaints about an item, and the company wants to stop all transactions, both purchase and sale, with that item until the dealer has clarified the issue with his supplier and possibly received a replacement for the defective stock. Another common example is during counting the physical inventory using cycle counting where the counting is done in one section of a warehouse at a time, so that the regular operations can continue in the other parts of the warehouse. In these situations, it is necessary to block all transactions, such as picks and put-aways, for a bin while warehouse counting is in progress for that bin.</p>
|
||||
<p>In contrast, a permanent halt to transactions could be required when an item has become obsolete (or is about to become obsolete), and the company wants to stop further purchase or sale of the item. However, the company wants to maintain the transaction history of the item and, therefore, does not want to delete the item record.</p>
|
||||
|
|
@ -320,7 +320,7 @@ ALGuidelines.Dev
|
|||
<li>Bin</li>
|
||||
</ul>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>The <a href=/nav/w/designpatterns/115.released-entity.aspx>Released Entity</a>.</p>
|
||||
<p>The <a href=/navpatterns/1-patterns/released-entity/>Released Entity</a>.</p>
|
||||
<div style=position:relative;padding-bottom:56.25%;height:0;overflow:hidden>
|
||||
<iframe src=https://www.youtube.com/embed/O2R-fTSup1o style=position:absolute;top:0;left:0;width:100%;height:100%;border:0 allowfullscreen title="YouTube Video"></iframe>
|
||||
</div>
|
||||
|
|
@ -336,12 +336,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Cached Web Server Calls :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600598 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600598></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/cached-web-service-calls/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600598></script>
|
||||
<script src=/js/auto-complete.js?1644600598></script>
|
||||
<script src=/js/search.js?1644600598></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -338,26 +338,28 @@ OnAction=<span style=color:#66d9ef>VAR</span>
|
|||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> IdentifyCountryRegionCode@<span style=color:#ae81ff>1</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> BankDataConvBank@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1259</span>;<span style=color:#66d9ef>Filter</span>@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Text</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
CompanyInformation@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>79</span>;
|
||||
BlankFilter@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
BlankFilter <span style=color:#f92672>:=</span> <span style=color:#e6db74>''''''</span>;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#66d9ef>Filter</span> = BlankFilter <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
CompanyInformation<span style=color:#f92672>.</span>GET;
|
||||
BankDataConvBank<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Country/Region Code",CompanyInformation<span style=color:#f92672>.</span>"Country/Region Code"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>BankDataConvBank<span style=color:#f92672>.</span>GETFILTER<span style=color:#f92672>(</span>"Country/Region Code"<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span><span style=color:#66d9ef>Filter</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
CompanyInformation@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>79</span>;
|
||||
BlankFilter@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
BlankFilter <span style=color:#f92672>:=</span> <span style=color:#e6db74>''''''</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#66d9ef>Filter</span> = BlankFilter <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
CompanyInformation<span style=color:#f92672>.</span>GET;
|
||||
BankDataConvBank<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Country/Region Code",CompanyInformation<span style=color:#f92672>.</span>"Country/Region Code"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>BankDataConvBank<span style=color:#f92672>.</span>GETFILTER<span style=color:#f92672>(</span>"Country/Region Code"<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span><span style=color:#66d9ef>Filter</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> RefreshBankNamesOlderThanToday@<span style=color:#ae81ff>5</span><span style=color:#f92672>(</span>CountryRegionCode@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Text</span>;ShowErrors@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>Boolean</span>;Timeout@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankDataConvBank@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1259</span>;
|
||||
ImpBankListExtDataHndl@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1289</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> CountryRegionCode <\> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
BankDataConvBank<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Country/Region Code",CountryRegionCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankDataConvBank@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1259</span>;
|
||||
ImpBankListExtDataHndl@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1289</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> CountryRegionCode <> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
BankDataConvBank<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Country/Region Code",CountryRegionCode<span style=color:#f92672>)</span>;
|
||||
BankDataConvBank<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Last Update Date",<span style=color:#e6db74>'<%1'</span>,TODAY<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> BankDataConvBank<span style=color:#f92672>.</span>FINDFIRST <span style=color:#66d9ef>THEN</span>
|
||||
ImpBankListExtDataHndl<span style=color:#f92672>.</span>GetBankListFromConversionService<span style=color:#f92672>(</span>ShowErrors,CountryRegionCode,Timeout<span style=color:#f92672>)</span>;
|
||||
|
|
@ -378,12 +380,12 @@ OnAction=<span style=color:#66d9ef>VAR</span>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600598></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600598></script>
|
||||
<script src=/js/featherlight.min.js?1644600598></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600598></script>
|
||||
<script src=/js/relearn.js?1644600598></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Conditional Cascading Update :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600598 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600598 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600598></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/conditional-cascading-update/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600598></script>
|
||||
<script src=/js/auto-complete.js?1644600598></script>
|
||||
<script src=/js/search.js?1644600598></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -288,12 +288,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600598></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600598></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600598></script>
|
||||
<script src=/js/featherlight.min.js?1644600598></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600598></script>
|
||||
<script src=/js/relearn.js?1644600598></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Copy Document :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/copy-document/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -291,12 +291,20 @@ ALGuidelines.Dev
|
|||
</ul>
|
||||
<p>The Copy Document pattern involves the following entities:</p>
|
||||
<ol>
|
||||
<li>Source document tables for document header and line. For example,Sales Header/Line.</li>
|
||||
<li>Destination document tables for document header and line.</li>
|
||||
<li>
|
||||
<p>Source document tables for document header and line. For example,Sales Header/Line.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Destination document tables for document header and line.<br>
|
||||
<strong>Note:</strong> The source document header/line and destination document header/line tables do not need to be the same. For example, you can copy a Sales Shipment Header/Lines into a Sales Header/Lines.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Copy Document engine: COD6620, Copy Document Mgt.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Copy Document report for a specific document type. The report requires the following parameters:</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>**Note:**The source document header/line and destination document header/line tables do not need to be the same. For example, you can copy a Sales Shipment Header/Lines into a Sales Header/Lines.
|
||||
3. Copy Document engine: COD6620, Copy Document Mgt.
|
||||
4. Copy Document report for a specific document type. The report requires the following parameters:</p>
|
||||
<ul>
|
||||
<li>Source Document Type</li>
|
||||
<li>Source Document No.</li>
|
||||
|
|
@ -319,7 +327,7 @@ ALGuidelines.Dev
|
|||
<p><a href=clip_image004.gif-750x0.png><img src=clip_image004.gif-750x0.png alt=" "></a></p>
|
||||
<p>Example: Copy Sales Document for Credit Memos.</p>
|
||||
<p>In the standard version of Microsoft Dynamics NAV, the Copy Document functionality is implemented in the Sales Credit Memo window as shown in the following section.</p>
|
||||
<p>***</p>
|
||||
<hr>
|
||||
<p><strong>Precondition</strong>: The user enters data in PAGE44, Sales Credit Memo.</p>
|
||||
<p><a href=clip_5F00_image006.jpg><img src=clip_5F00_image006.jpg alt=" "></a></p>
|
||||
<p><strong>Step 1</strong>: The user runs REP292, Copy Sales Document from the Sales Credit Memo window, populating the required parameters. The Include Header and Recalculate Lines fields are selected.</p>
|
||||
|
|
@ -349,12 +357,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Create Data from Templates :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/create-data-from-templates/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -281,7 +281,7 @@ ALGuidelines.Dev
|
|||
<p>As a first step, we must insert a record. This can be done either through C/AL code or by letting the user create a record using the <strong>New</strong> action.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>After the record is created, we must apply the template. This is done by using the <strong>UpdateRecord</strong> function in the **Config. Template Management **codeunit (8612).</p>
|
||||
<p>After the record is created, we must apply the template. This is done by using the <strong>UpdateRecord</strong> function in the <strong>Config. Template Management</strong> codeunit (8612).</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p><strong>Config. Template Lines</strong> records reference one <strong>Config. Template Header</strong> record (lines pattern). The lines can be of type:</p>
|
||||
|
|
@ -290,34 +290,41 @@ ALGuidelines.Dev
|
|||
<li><strong>Related</strong> Template – References a Config. Template Header record for a related template.</li>
|
||||
</ul>
|
||||
<p>The <strong>UpdateRecord</strong> function applies values to the record one line at the time. One of the requirements was to be possible to use configuration templates in different language/regional settings than the template was created in.</p>
|
||||
<p>To support this scenario, when applying the<strong>Config. Template Line</strong> record, <strong>GLOBALLANGUAGE</strong> is set to the language ID of the field. This is important because the default value is stored as text, so we need to use the same formatting that NAV was running on when the template was created. Otherwise, data types, such as Boolean, Date, etc., will raise validation errors.</p>
|
||||
<p>To support this scenario, when applying the <strong>Config. Template Line</strong> record, <strong>GLOBALLANGUAGE</strong> is set to the language ID of the field. This is important because the default value is stored as text, so we need to use the same formatting that NAV was running on when the template was created. Otherwise, data types, such as Boolean, Date, etc., will raise validation errors.</p>
|
||||
<p>Any updates to a <strong>Config. Template Line</strong> record will automatically update the language ID to the current one. Since lines are applied one by one, it is supported to have lines with different language IDs belonging to the same template.</p>
|
||||
<ol start=3>
|
||||
<li>After we have applied the template to the record, we can insert related templates. For example, when you insert an item, you may want to insert dimensions as well. You must implement the logic to apply or then modify the related templates, since this depends on the logic and the relationship between the records. Lines with <strong>Type = Related Template</strong> are used to reference related templates.</li>
|
||||
</ol>
|
||||
<p>Code example (Insert a record, apply a template, and insert the related templates):</p>
|
||||
<p><strong>// First insert a record Customer.INSERT(TRUE);</strong></p>
|
||||
<p><strong>// Apply a template RecRef.GETTABLE(Customer);</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>ConfigTemplateMgt<span style=color:#f92672>.</span>UpdateRecord<span style=color:#f92672>(</span>ConfigTemplateHeader,RecRef<span style=color:#f92672>)</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#75715e>// First insert a record Customer.INSERT(TRUE);
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#75715e>// Apply a template RecRef.GETTABLE(Customer);
|
||||
</span><span style=color:#75715e></span>
|
||||
ConfigTemplateMgt<span style=color:#f92672>.</span>UpdateRecord<span style=color:#f92672>(</span>ConfigTemplateHeader,RecRef<span style=color:#f92672>)</span>;
|
||||
RecRef<span style=color:#f92672>.</span>SETTABLE<span style=color:#f92672>(</span>Customer<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p><strong>// Insert Dimensions – related templates</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>MiniDimensionsTemplate<span style=color:#f92672>.</span>InsertDimensionsFromTemplates<span style=color:#f92672>(</span>ConfigTemplateHeader,Customer<span style=color:#f92672>.</span>"No.",<span style=color:#66d9ef>DATABASE</span>::Customer<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// Insert Dimensions -- related templates
|
||||
</span><span style=color:#75715e></span>
|
||||
MiniDimensionsTemplate<span style=color:#f92672>.</span>InsertDimensionsFromTemplates<span style=color:#f92672>(</span>ConfigTemplateHeader,Customer<span style=color:#f92672>.</span>"No.",<span style=color:#66d9ef>DATABASE</span>::Customer<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Code to insert related templates (dimensions):</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>FUNCTION</span> InsertDimensionsFromTemplates<span style=color:#f92672>(</span>ConfigTemplateHeader : <span style=color:#66d9ef>Record</span> "Config. Template Header";MasterRecordNo : <span style=color:#66d9ef>Code</span>\[<span style=color:#ae81ff>20</span>\];TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>FUNCTION</span> InsertDimensionsFromTemplates<span style=color:#f92672>(</span>ConfigTemplateHeader : <span style=color:#66d9ef>Record</span> "Config. Template Header";MasterRecordNo : <span style=color:#66d9ef>Code</span>[<span style=color:#ae81ff>20</span>];TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672> </span><span style=color:#75715e>// There are multiple records (multiple dimensions per master record)
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// We have to set filter
|
||||
</span><span style=color:#75715e></span> ConfigTemplateLine<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span><span style=color:#66d9ef>Type</span>,ConfigTemplateLine<span style=color:#f92672>.</span><span style=color:#66d9ef>Type</span>::"Related Template"<span style=color:#f92672>)</span>;
|
||||
ConfigTemplateLine<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Data Template Code",ConfigTemplateHeader<span style=color:#f92672>.</span><span style=color:#66d9ef>Code</span>
|
||||
<span style=color:#66d9ef>IF</span> ConfigTemplateLine<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
ConfigTemplateHeader<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>ConfigTemplateLine<span style=color:#f92672>.</span>"Template Code"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// Ensure that the table where the template belongs to is Dimensions
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// We could have other related templates
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>IF</span> ConfigTemplateHeader<span style=color:#f92672>.</span>"Table ID" = <span style=color:#66d9ef>DATABASE</span>::"Default Dimension" <span style=color:#66d9ef>THEN</span>
|
||||
InsertDimensionFromTemplate<span style=color:#f92672>(</span>ConfigTemplateHeader,MasterRecordNo,TableID<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> ConfigTemplateLine<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
</code></pre></div><p><strong>// Create a new Dimensions Record and link it to the Master Record</strong>****</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>FUNCTION</span> InsertDimensionFromTemplate<span style=color:#f92672>(</span>ConfigTemplateHeader : <span style=color:#66d9ef>Record</span> "Config. Template Header";MasterRecordNo : <span style=color:#66d9ef>Code</span>\[<span style=color:#ae81ff>20</span>\];TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
ConfigTemplateHeader<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>ConfigTemplateLine<span style=color:#f92672>.</span>"Template Code"<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// Ensure that the table where the template belongs to is Dimensions
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// We could have other related templates
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>IF</span> ConfigTemplateHeader<span style=color:#f92672>.</span>"Table ID" = <span style=color:#66d9ef>DATABASE</span>::"Default Dimension" <span style=color:#66d9ef>THEN</span>
|
||||
InsertDimensionFromTemplate<span style=color:#f92672>(</span>ConfigTemplateHeader,MasterRecordNo,TableID<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> ConfigTemplateLine<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
|
||||
<span style=color:#75715e>// Create a new Dimensions Record and link it to the Master Record
|
||||
</span><span style=color:#75715e></span><span style=color:#66d9ef>FUNCTION</span> InsertDimensionFromTemplate<span style=color:#f92672>(</span>ConfigTemplateHeader : <span style=color:#66d9ef>Record</span> "Config. Template Header";MasterRecordNo : <span style=color:#66d9ef>Code</span>[<span style=color:#ae81ff>20</span>];TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span>DefaultDimension<span style=color:#f92672>.</span>INIT;
|
||||
DefaultDimension<span style=color:#f92672>.</span>"No." <span style=color:#f92672>:=</span> MasterRecordNo;
|
||||
DefaultDimension<span style=color:#f92672>.</span>"Table ID" <span style=color:#f92672>:=</span> TableID;
|
||||
|
|
@ -335,7 +342,7 @@ RecRef<span style=color:#f92672>.</span>SETTABLE<span style=color:#f92672>(</spa
|
|||
<p><strong>Note:</strong> In Microsoft Dynamics C5 2014, we chose to remove the <strong>New</strong> action with configuration since we wanted to promote the functionality and avoid the confusion in having too many options. However this might be difficult to maintain with a larger set of pages.</p>
|
||||
<p><strong>To view or edit templates, you have two options:</strong></p>
|
||||
<ol>
|
||||
<li>Use the <strong>Config. Template List</strong> table (8620) and the **Config. Template Header Card **table (8618).</li>
|
||||
<li>Use the <strong>Config. Template List</strong> table (8620) and the <strong>Config. Template Header Card</strong> table (8618).</li>
|
||||
</ol>
|
||||
<p>This is a generic solution that is not very usable and is error-prone (no lookups, checks for length, table relation checks, etc.) The default value is a text field of 250 characters, which might be much more than the field length, and may lead to validation errors when used. Users will most likely not be able to use this page.</p>
|
||||
<p><a href=2816.Picture3.png><img src=2816.Picture3.png alt=" "></a></p>
|
||||
|
|
@ -350,8 +357,8 @@ RecRef<span style=color:#f92672>.</span>SETTABLE<span style=color:#f92672>(</spa
|
|||
<li>To avoid any lateral effects of doing validation on the temporary master record. Doing validation on fields, even though the record itself is temporary, could permanently modify other data in the database. For example, if you insert a new record in the <strong>Customer</strong> table, even in a temporary table, a Contact record is created, which will not be temporary.</li>
|
||||
<li>Testability: It is easy to test through RecordRef that the template table matches the main table. We can compare field lengths, data types, table relations, etc. The test is able to detect that they are out of sync, so it is easy to prevent errors.</li>
|
||||
</ul>
|
||||
<p>One example in the product is the **Mini Customer Template **table (1300).</p>
|
||||
<p>The table itself contains very little code. OnModify, OnInsert, and OnDelete triggers update the <strong>Configuration Header</strong> and <strong>Configuration Lines</strong> tables. The following functions in the **Config. Template Management **codeunit (8612), are used for this:</p>
|
||||
<p>One example in the product is the <strong>Mini Customer Template</strong> table (1300).</p>
|
||||
<p>The table itself contains very little code. OnModify, OnInsert, and OnDelete triggers update the <strong>Configuration Header</strong> and <strong>Configuration Lines</strong> tables. The following functions in the <strong>Config. Template Management</strong> codeunit (8612), are used for this:</p>
|
||||
<ul>
|
||||
<li>ConfigTemplateManagement.CreateConfigTemplateAndLines</li>
|
||||
<li>ConfigTemplateManagement.UpdateConfigTemplateAndLines</li>
|
||||
|
|
@ -366,11 +373,10 @@ RecRef<span style=color:#f92672>.</span>SETTABLE<span style=color:#f92672>(</spa
|
|||
<h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<p>In C5 2014, this is the workflow:</p>
|
||||
<p>The user opens the <strong>Customers List</strong> window and selects <strong>New</strong></p>
|
||||
<p>**<a href=4341.Picture4.png><img src=4341.Picture4.png alt=" "></a>**</p>
|
||||
<p><strong><a href=4341.Picture4.png></a></strong></p>
|
||||
<p><a href=4341.Picture4.png><img src=4341.Picture4.png alt=" "></a></p>
|
||||
<p>From this page, the user can view the template, edit it, or create a new one. Selecting a template will populate the customer card and open a new record. From the existing record, the user has options to save as a template or opening a list of templates to maintain available templates. Selecting a template will populate the customer card and open a new record. From the existing record, the user has options to save as a template or opening a list of templates to maintain available templates.</p>
|
||||
<p><a href=3482.Picture-5.png><img src=3482.Picture-5.png alt=" "></a></p>
|
||||
<p>From the **Customer Card Template **window, we can invoke the <strong>Dimensions</strong> action, through which we can define the dimensions that will be inserted together with the template:</p>
|
||||
<p>From the <strong>Customer Card Template</strong> window, we can invoke the <strong>Dimensions</strong> action, through which we can define the dimensions that will be inserted together with the template:</p>
|
||||
<p><a href=2134.Picture6.png><img src=2134.Picture6.png alt=" "></a></p>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>This pattern is used in Microsoft Dynamics C5 2014 in the following objects:</p>
|
||||
|
|
@ -428,12 +434,12 @@ RecRef<span style=color:#f92672>.</span>SETTABLE<span style=color:#f92672>(</spa
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Create URLs to NAV Clients :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/create-urls-to-nav-clients/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -301,218 +301,235 @@ GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</sp
|
|||
</ul>
|
||||
<h2 id=examples-of-usage>Examples of Usage</h2>
|
||||
<p>The following are examples of calls to GETURL and their corresponding return value:</p>
|
||||
<p><strong>Command</strong></p>
|
||||
<p><strong>URL</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Win<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71//
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/Services
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Current<span style=color:#f92672>) </span>ie<span style=color:#f92672>. </span>When running this <span style=color:#66d9ef>code</span> on a Win client session
|
||||
|
||||
dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71//
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Default<span style=color:#f92672>) </span>ie<span style=color:#f92672>. </span>When the Server config <span style=color:#66d9ef>key</span> DefaultClient is set <span style=color:#66d9ef>to</span> Windows
|
||||
|
||||
dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71//
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,<span style=color:#e6db74>''</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71//
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,<span style=color:#e6db74>'NONEXISTING Corp'</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/NONEXISTING Corp/
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=CRONUS
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,<span style=color:#e6db74>''</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,<span style=color:#e6db74>'NONEXISTING Corp'</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=NONEXISTING Corp
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData/Company('CRONUS')
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,<span style=color:#e6db74>''</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,<span style=color:#e6db74>'NONEXISTING Corp'</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData/Company('NONEXISTING Corp')
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/CRONUS/Services
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,<span style=color:#e6db74>''</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/Services
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,<span style=color:#e6db74>'NONEXISTING Corp'</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/NONEXISTING Corp/Services
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Table</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runtable?table=27
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=27
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Report</span>,<span style=color:#ae81ff>6</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runreport?report=6
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Codeunit</span>,<span style=color:#ae81ff>5065</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runcodeunit?codeunit=5065
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Query</span>,<span style=color:#ae81ff>9150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runquery?query=9150
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>XmlPort</span>,<span style=color:#ae81ff>5150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runxmlport?xmlport=5150
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>) </span>ie<span style=color:#f92672>. </span>When the Web Service is published
|
||||
|
||||
http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData/Company('CRONUS')/PAG27Vendors
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Query</span>,<span style=color:#ae81ff>9150</span><span style=color:#f92672>) </span>ie<span style=color:#f92672>. </span>When the Web Service is published
|
||||
|
||||
http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData/Company('CRONUS')/QUE9150MyCustomers
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)</span>Â ie<span style=color:#f92672>. </span>When the Web Service is published
|
||||
|
||||
http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/CRONUS/Page/PAG27Vendors
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Codeunit</span>,<span style=color:#ae81ff>5065</span><span style=color:#f92672>) </span>ie<span style=color:#f92672>. </span>When the Web Service is published
|
||||
|
||||
http:<span style=color:#75715e>//MyServer:7047/DynamicsNAV71/WS/CRONUS/Codeunit/COD5065EmailLogging
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>) </span><span style=color:#66d9ef>List</span> <span style=color:#66d9ef>Page</span>
|
||||
|
||||
dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=27&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Windows,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>26</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>) </span>Card <span style=color:#66d9ef>Page</span>
|
||||
|
||||
dynamicsnav:<span style=color:#75715e>//MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=26&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>) </span><span style=color:#66d9ef>List</span> <span style=color:#66d9ef>Page</span>
|
||||
|
||||
https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=CRONUS&page=27&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>26</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>) </span>Card <span style=color:#66d9ef>Page</span>
|
||||
|
||||
https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=CRONUS&page=26&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>http:<span style=color:#75715e>//MyServer:7048/DynamicsNAV71/OData/Company('CRONUS')/PAG27Vendors('IC1030')
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=CRONUS&page=27
|
||||
</span><span style=color:#75715e></span>
|
||||
GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Report</span>,<span style=color:#ae81ff>6</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>https:<span style=color:#75715e>//navwebsrvr:443/DynamicsNAV71\_Instance1/Webclient?company=CRONUS&report=6
|
||||
</span><span style=color:#75715e></span>
|
||||
</code></pre></div><p>If the GETURL function is called with invalid parameters, it will return an empty string. In that case, you can find the related error text by calling the GETLASTERRORTEXT function.</p>
|
||||
<p><strong>Function Call</strong></p>
|
||||
<p><strong>Error Message</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Table</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Codeunit</span>,<span style=color:#ae81ff>5065</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Query</span>,<span style=color:#ae81ff>9150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::Web,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>XmlPort</span>,<span style=color:#ae81ff>5150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Table</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The <span style=color:#66d9ef>Page</span> object, <span style=color:#ae81ff>27</span>, that is specified <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> has <span style=color:#f92672>not</span> been published <span style=color:#66d9ef>in</span> the Web Services <span style=color:#66d9ef>table</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Report</span>,<span style=color:#ae81ff>6</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Codeunit</span>,<span style=color:#ae81ff>5065</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Query</span>,<span style=color:#ae81ff>9150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The <span style=color:#66d9ef>Query</span> object, <span style=color:#ae81ff>9150</span>, that is specified <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> has <span style=color:#f92672>not</span> been published <span style=color:#66d9ef>in</span> the Web Services <span style=color:#66d9ef>table</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::OData,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>XmlPort</span>,<span style=color:#ae81ff>5150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Table</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The <span style=color:#66d9ef>Page</span> object, <span style=color:#ae81ff>27</span>, that is specified <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> has <span style=color:#f92672>not</span> been published <span style=color:#66d9ef>in</span> the Web Services <span style=color:#66d9ef>table</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Report</span>,<span style=color:#ae81ff>6</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Codeunit</span>,<span style=color:#ae81ff>5065</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The <span style=color:#66d9ef>Codeunit</span> object, <span style=color:#ae81ff>5065</span>, that is specified <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> has <span style=color:#f92672>not</span> been published <span style=color:#66d9ef>in</span> the Web Services <span style=color:#66d9ef>table</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Query</span>,<span style=color:#ae81ff>9150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>XmlPort</span>,<span style=color:#ae81ff>5150</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The specified object <span style=color:#66d9ef>type</span> parameter <span style=color:#66d9ef>for</span> the GetUrl <span style=color:#66d9ef>function</span> is <span style=color:#f92672>not</span> valid<span style=color:#f92672>.
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</span>::SOAP,COMPANYNAME,<span style=color:#66d9ef>OBJECTTYPE</span>::<span style=color:#66d9ef>Page</span>,<span style=color:#ae81ff>27</span>,<span style=color:#66d9ef>record</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span></code></pre></div><p>You cannot specify a record parameter for the GetUrl function when the object type is SOAP</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Win)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71//</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web)</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData)</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP)</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/Services</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Current) ie. When running this code on a Win client session</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71//</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Default) ie. When the Server config key DefaultClient is set to Windows</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71//</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,'')</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71//</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,‘NONEXISTING Corp’)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/NONEXISTING Corp/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME)</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=CRONUS</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,'')</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,‘NONEXISTING Corp’)</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=NONEXISTING Corp</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME)</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData/Company(‘CRONUS’)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,'')</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,‘NONEXISTING Corp’)</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData/Company(‘NONEXISTING Corp’)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME)</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/CRONUS/Services</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,'')</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/Services</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,‘NONEXISTING Corp’)</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/NONEXISTING Corp/Services</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Table,27)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runtable?table=27</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Page,27)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=27</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Report,6)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runreport?report=6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Codeunit,5065)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runcodeunit?codeunit=5065</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Query,9150)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runquery?query=9150</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::XmlPort,5150)</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runxmlport?xmlport=5150</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Page,27) ie. When the Web Service is published</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData/Company(‘CRONUS’)/PAG27Vendors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Query,9150) ie. When the Web Service is published</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData/Company(‘CRONUS’)/QUE9150MyCustomers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Page,27)Â ie. When the Web Service is published</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/CRONUS/Page/PAG27Vendors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Codeunit,5065) ie. When the Web Service is published</td>
|
||||
<td>http://MyServer:7047/DynamicsNAV71/WS/CRONUS/Codeunit/COD5065EmailLogging</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Page,27,record) List Page</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=27&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Windows,COMPANYNAME,OBJECTTYPE::Page,26,record) Card Page</td>
|
||||
<td>dynamicsnav://MyServer:7046/DynamicsNAV71/CRONUS/runpage?page=26&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Page,27,record) List Page</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=CRONUS&page=27&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Page,26,record) Card Page</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=CRONUS&page=26&bookmark=23;FwAAAAJ7/0kAQwAxADAAMwAw</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Page,27,record)</td>
|
||||
<td>http://MyServer:7048/DynamicsNAV71/OData/Company(‘CRONUS’)/PAG27Vendors(‘IC1030’)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Page,27)</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=CRONUS&page=27</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Report,6)</td>
|
||||
<td>https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=CRONUS&report=6</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>If the GETURL function is called with invalid parameters, it will return an empty string. In that case, you can find the related error text by calling the GETLASTERRORTEXT function.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function Call</th>
|
||||
<th>Error Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Table,27)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Codeunit,5065)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::Query,9150)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::Web,COMPANYNAME,OBJECTTYPE::XmlPort,5150)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Table,27)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Page,27)</td>
|
||||
<td>The Page object, 27, that is specified for the GetUrl function has not been published in the Web Services table.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Report,6)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Codeunit,5065)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Query,9150)</td>
|
||||
<td>The Query object, 9150, that is specified for the GetUrl function has not been published in the Web Services table.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::XmlPort,5150)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Table,27)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Page,27)</td>
|
||||
<td>The Page object, 27, that is specified for the GetUrl function has not been published in the Web Services table.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Report,6)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Codeunit,5065)</td>
|
||||
<td>The Codeunit object, 5065, that is specified for the GetUrl function has not been published in the Web Services table.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Query,9150)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::XmlPort,5150)</td>
|
||||
<td>The specified object type parameter for the GetUrl function is not valid.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Page,27,record)</td>
|
||||
<td>You cannot specify a record parameter for the GetUrl function when the object type is SOAP</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<p>The following example shows how to use the GETURL function in codeunit 440 to ensure that the notification mail in Document Approvals can link to both the Microsoft Dynamics NAV Windows client and the Microsoft Dynamics NAV web client:</p>
|
||||
<p><a href=1778.url1.jpg><img src=1778.url1.jpg alt=" "></a></p>
|
||||
|
|
@ -531,12 +548,12 @@ GETURL<span style=color:#f92672>(</span><span style=color:#66d9ef>CLIENTTYPE</sp
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Creating Custom Charts :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/creating-custom-charts/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -299,7 +299,7 @@ ALGuidelines.Dev
|
|||
<li>DrillDown logic</li>
|
||||
<li>Other helper data related functions, for displaying date, periods, etc.[Bogdana1] [NK2] [NK3]</li>
|
||||
</ul>
|
||||
<p><strong>Note:</strong> It is recommended that you reuse the <strong>Business Chart Buffer <strong>table</strong></strong>(485) as a buffer table or extend. It is a generic table which should cover most of the use cases. Implement a new buffer table only if this table does not meet your needs.</p>
|
||||
<p><strong>Note:</strong> It is recommended that you reuse the <strong>Business Chart Buffer table</strong> (485) as a buffer table or extend. It is a generic table which should cover most of the use cases. Implement a new buffer table only if this table does not meet your needs.</p>
|
||||
<h3 id=cardpart-page>CardPart page</h3>
|
||||
<p>The CardPart page hosts the Business Chart add-in and must use the add-in buffer table as a source table.</p>
|
||||
<p>On the page, you must implement the following triggers:</p>
|
||||
|
|
@ -322,10 +322,10 @@ ALGuidelines.Dev
|
|||
<p>To do this, you need the following:</p>
|
||||
<ul>
|
||||
<li>A setup record to store the data. You can use the <strong>Business Chart User Setup</strong> table (487) or create a new setup table if you need to store more information.</li>
|
||||
<li>A management codeunit to write/apply the settings to the chart and to encapsulate other logic. Since we should not write code on pages, the code for the actions and other logic that does not apply to the setup record****should go in this codeunit.</li>
|
||||
<li>A management codeunit to write/apply the settings to the chart and to encapsulate other logic. Since we should not write code on pages, the code for the actions and other logic that does not apply to the setup record should go in this codeunit.</li>
|
||||
<li>Setup pages where users can customize how the chart is shown and set different settings.</li>
|
||||
</ul>
|
||||
<p>The relation between the components is visualized in the following diagram[</p>
|
||||
<p>The relation between the components is visualized in the following diagram:</p>
|
||||
<p><a href=0246.Picture6.png><img src=0246.Picture6.png alt=" "></a></p>
|
||||
<h3 id=optional-show-multiple-charts-within-a-single-cardpart>Optional: Show Multiple Charts within a Single CardPart</h3>
|
||||
<p>This option is useful on a Role Center where you want to show multiple charts using different datasets within a single part. In that case, you need a record to store the last chart selection, the setup records, and code units for separate charts.</p>
|
||||
|
|
@ -339,24 +339,29 @@ ALGuidelines.Dev
|
|||
<h3 id=nav-specific-example-1>NAV Specific Example 1</h3>
|
||||
<p>Implementation of the <strong>Finance Performance Chart</strong> page (762)</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>BusinessChart::AddInReady<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672> </span>UpdateChart<span style=color:#f92672>(</span>Period::" "<span style=color:#f92672>)</span>;
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>UpdateChart<span style=color:#f92672>(</span>Period::" "<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> UpdateChart<span style=color:#f92672>(</span>Period : <span style=color:#e6db74>',Next,Previous'</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span>MoveAndUpdateChart<span style=color:#f92672>(</span>Period,<span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>;
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>MoveAndUpdateChart<span style=color:#f92672>(</span>Period,<span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> MoveAndUpdateChart<span style=color:#f92672>(</span>Period : <span style=color:#e6db74>',Next,Previous'</span>;Move : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span>AccSchedChartManagement<span style=color:#f92672>.</span>GetSetupRecordset<span style=color:#f92672>(</span>AccountSchedulesChartSetup,AccountSchedulesChartSetup<span style=color:#f92672>.</span>Name,Move<span style=color:#f92672>)</span>;
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>AccSchedChartManagement<span style=color:#f92672>.</span>GetSetupRecordset<span style=color:#f92672>(</span>AccountSchedulesChartSetup,AccountSchedulesChartSetup<span style=color:#f92672>.</span>Name,Move<span style=color:#f92672>)</span>;
|
||||
|
||||
AccSchedChartManagement<span style=color:#f92672>.</span>UpdateData<span style=color:#f92672>(</span>Rec,Period,AccountSchedulesChartSetup<span style=color:#f92672>)</span>;
|
||||
AccSchedChartManagement<span style=color:#f92672>.</span>UpdateData<span style=color:#f92672>(</span>Rec,Period,AccountSchedulesChartSetup<span style=color:#f92672>)</span>;
|
||||
|
||||
Update<span style=color:#f92672>(</span>CurrPage<span style=color:#f92672>.</span>BusinessChart<span style=color:#f92672>)</span>;
|
||||
Update<span style=color:#f92672>(</span>CurrPage<span style=color:#f92672>.</span>BusinessChart<span style=color:#f92672>)</span>;
|
||||
|
||||
StatusText <span style=color:#f92672>:=</span> GetCurrentSelectionText<span style=color:#f92672>(</span>"Period Filter Start Date","Period Filter End Date"<span style=color:#f92672>)</span>;
|
||||
StatusText <span style=color:#f92672>:=</span> GetCurrentSelectionText<span style=color:#f92672>(</span>"Period Filter Start Date","Period Filter End Date"<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>In the MoveAndUpdateChart method, the AccSchedChartManagement codeunit gets a setup record and updates it if necessary. Then, it initializes the chart with setup data and sets the StatusText to show the period for which data is displayed. The same method is used by the actions to move and update the chart so that there is no code duplication.</p>
|
||||
<p>The following code is used to implement <strong>DataPointClicked</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>BusinessChart::DataPointClicked<span style=color:#f92672>(</span>point : <span style=color:#66d9ef>DotNet</span> "Microsoft.Dynamics.Nav.Client.BusinessChart.BusinessChartDataPoint"<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span>SetDrillDownIndexes<span style=color:#f92672>(</span>point<span style=color:#f92672>)</span>;
|
||||
AccSchedChartManagement<span style=color:#f92672>.</span>DrillDown<span style=color:#f92672>(</span>Rec,AccountSchedulesChartSetup<span style=color:#f92672>)</span>;
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>SetDrillDownIndexes<span style=color:#f92672>(</span>point<span style=color:#f92672>)</span>;
|
||||
|
||||
AccSchedChartManagement<span style=color:#f92672>.</span>DrillDown<span style=color:#f92672>(</span>Rec,AccountSchedulesChartSetup<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>SetDrillDownindexes is a method from the <strong>Business Chart Buffer</strong> table that maps the DotNet point variable to C/AL data, so it must be used. The next method that you must implement is the action to be performed on Drilldown.</p>
|
||||
<p>The <strong>DataPointDoubleClicked</strong> trigger has the same implementation logic as the DataPointClicked trigger.</p>
|
||||
<h3 id=nav-specific-example-2>NAV Specific Example 2</h3>
|
||||
|
|
@ -408,12 +413,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Cross Session Events :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/cross-session-events/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -280,100 +280,163 @@ ALGuidelines.Dev
|
|||
<li><strong>Message Queue</strong>: To hold the messages for each Subscriber. Generally once these messages are read, they are deleted.</li>
|
||||
</ul>
|
||||
<h2 id=example>Example</h2>
|
||||
<p>An example of this would be when we have multiple users looking at the same set of data and we want their screens to update in “real time” whenever one of them makes a change, without doing a full refresh. We will use the <a href=/nav/w/designpatterns/248.observer>Observer pattern</a> to capture the change (act as the Publisher) and then create a Table to hold Subscribers and Filters (Change Observer), a Table to be the Message Queue (Change Notification), and a Codeunit to be the Message Broker and help with the polling (ObserverMgt).</p>
|
||||
<p>An example of this would be when we have multiple users looking at the same set of data and we want their screens to update in “real time” whenever one of them makes a change, without doing a full refresh. We will use the <a href=/navpatterns/1-patterns/observer/>Observer pattern</a> to capture the change (act as the Publisher) and then create a Table to hold Subscribers and Filters (Change Observer), a Table to be the Message Queue (Change Notification), and a Codeunit to be the Message Broker and help with the polling (ObserverMgt).</p>
|
||||
<p>Below are the table definitions:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> <span style=color:#75715e>//Change Observer:
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>//"Table ID" Integer "Observable Table"
|
||||
</span><span style=color:#75715e></span> "Server ID" <span style=color:#66d9ef>Integer</span>
|
||||
"Session ID" <span style=color:#66d9ef>Integer</span>
|
||||
|
||||
<span style=color:#75715e>//Change Notification:
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>//"Table ID" Integer "Observable Table"
|
||||
</span><span style=color:#75715e></span> "Server ID" <span style=color:#66d9ef>Integer</span>
|
||||
"Session ID" <span style=color:#66d9ef>Integer</span>
|
||||
"Entry No." <span style=color:#66d9ef>Integer</span> AutoIncrement
|
||||
"Type of Change" <span style=color:#66d9ef>Option</span> Insert,<span style=color:#66d9ef>Modify</span>,Delete,Rename
|
||||
"Record ID" <span style=color:#66d9ef>RecordID</span>
|
||||
<span style=color:#f92672>... (</span>other <span style=color:#66d9ef>fields</span> <span style=color:#66d9ef>to</span> indicate what has changed<span style=color:#f92672>)
|
||||
</span></code></pre></div><p>The Change Observer table identifies the Subscriber using Server ID and Session ID, and then in this example there is only one filter, which is the Table ID we want to listen to any changes. In this case all three fields are in the Primary Key.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><strong>Change Observer:</strong></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>“Table ID”</td>
|
||||
<td>Integer</td>
|
||||
<td>“Observable Table”</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Server ID”</td>
|
||||
<td>Integer</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Session ID”</td>
|
||||
<td>Integer</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><strong>Change Notification:</strong></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>“Table ID”</td>
|
||||
<td>Integer</td>
|
||||
<td>“Observable Table”</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Server ID”</td>
|
||||
<td>Integer</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Session ID”</td>
|
||||
<td>Integer</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Entry No.”</td>
|
||||
<td>Integer</td>
|
||||
<td>AutoIncrement</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Type of Change”</td>
|
||||
<td>Option</td>
|
||||
<td>Insert,Modify,Delete,Rename</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>“Record ID”</td>
|
||||
<td>RecordID</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>… (other fields to indicate what has changed)</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The Change Observer table identifies the Subscriber using Server ID and Session ID, and then in this example there is only one filter, which is the Table ID we want to listen to any changes. In this case all three fields are in the Primary Key.</p>
|
||||
<p>The Change Notification table then has the same three fields plus an Entry No. as its Primary Key, and in this example borrows heavily from the Change Log code to fill in the rest of the message.</p>
|
||||
<p><em><strong>Note:</strong></em> Other examples of the pattern could have very different fields to identify the Subscriber, Filters and then whatever fields needed for content of the Message.</p>
|
||||
<p>Our Message Broker Codeunit will also serve as a central place to create Subscribers (Listen and StopListening functions) and a place to Poll for Messages. Note that the Poll function deletes the Messages as it reads them.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> <span style=color:#75715e>//Listen(TableID : Integer)**
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
"Table ID" <span style=color:#f92672>:=</span> TableID;
|
||||
"Server ID" <span style=color:#f92672>:=</span> SERVICEINSTANCEID;
|
||||
"Session ID" <span style=color:#f92672>:=</span> SESSIONID;
|
||||
INSERT<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
COMMIT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>Listen<span style=color:#f92672>(</span>TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
"Table ID" <span style=color:#f92672>:=</span> TableID;
|
||||
"Server ID" <span style=color:#f92672>:=</span> SERVICEINSTANCEID;
|
||||
"Session ID" <span style=color:#f92672>:=</span> SESSIONID;
|
||||
INSERT<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
COMMIT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#75715e>//StopListening(TableID : Integer)
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Server ID",SERVICEINSTANCEID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Session ID",SESSIONID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",TableID<span style=color:#f92672>)</span>;
|
||||
DELETEALL<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
COMMIT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
StopListening<span style=color:#f92672>(</span>TableID : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Server ID",SERVICEINSTANCEID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Session ID",SESSIONID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",TableID<span style=color:#f92672>)</span>;
|
||||
DELETEALL<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
COMMIT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#75715e>//NotifyAll(ChangeNotification : Record "Change Notification")**
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",ChangeNotification<span style=color:#f92672>.</span>"Table ID"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
Notify<span style=color:#f92672>(</span>Observer,ChangeNotification<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
NotifyAll<span style=color:#f92672>(</span>ChangeNotification : <span style=color:#66d9ef>Record</span> "Change Notification"<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>WITH</span> Observer <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",ChangeNotification<span style=color:#f92672>.</span>"Table ID"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
Notify<span style=color:#f92672>(</span>Observer,ChangeNotification<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#75715e>//Notify(Observer : Record "Change Observer";ChangeNotification : Record "Change Notification")**
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>WITH</span> ChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
"Server ID" <span style=color:#f92672>:=</span> Observer<span style=color:#f92672>.</span>"Server ID";
|
||||
"Session ID" <span style=color:#f92672>:=</span> Observer<span style=color:#f92672>.</span>"Session ID";
|
||||
"Entry No." <span style=color:#f92672>:=</span> <span style=color:#ae81ff>0</span>;
|
||||
INSERT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
Notify<span style=color:#f92672>(</span>Observer : <span style=color:#66d9ef>Record</span> "Change Observer";ChangeNotification : <span style=color:#66d9ef>Record</span> "Change Notification"<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>WITH</span> ChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
"Server ID" <span style=color:#f92672>:=</span> Observer<span style=color:#f92672>.</span>"Server ID";
|
||||
"Session ID" <span style=color:#f92672>:=</span> Observer<span style=color:#f92672>.</span>"Session ID";
|
||||
"Entry No." <span style=color:#f92672>:=</span> <span style=color:#ae81ff>0</span>;
|
||||
INSERT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#75715e>//Poll(TableID : Integer;VAR TempChangeNotification : TEMPORARY Record "Change Notification")**
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>WITH</span> ChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
TempChangeNotification<span style=color:#f92672>.</span>RESET;
|
||||
TempChangeNotification<span style=color:#f92672>.</span>DELETEALL;
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",TableID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Server ID",SERVICEINSTANCEID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Session ID",SESSIONID<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
TempChangeNotification <span style=color:#f92672>:=</span> ChangeNotification;
|
||||
TempChangeNotification<span style=color:#f92672>.</span>INSERT;
|
||||
MARK<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> NEXT = <span style=color:#ae81ff>0</span>;
|
||||
MARKEDONLY<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
DELETEALL;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><strong>__</strong> The final part of this example is an object that calls the functions above. In this example we will use a Page with a PingPong Timer Control to do the polling in (almost) real time. These are the functions on the page:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> <span style=color:#75715e>//OnQueryClosePage(CloseAction : Action None) : Boolean**
|
||||
</span><span style=color:#75715e></span> ObserverMgt<span style=color:#f92672>.</span>StopListening<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking"<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>//Timer::AddInReady()**
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>IF</span> ObserverMgt<span style=color:#f92672>.</span>Listen<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
CurrPage<span style=color:#f92672>.</span>Timer<span style=color:#f92672>.</span>Ping<span style=color:#f92672>(</span><span style=color:#ae81ff>1000</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>//Timer::Pong()**
|
||||
</span><span style=color:#75715e></span> CallUpdate;
|
||||
CurrPage<span style=color:#f92672>.</span>Timer<span style=color:#f92672>.</span>Ping<span style=color:#f92672>(</span><span style=color:#ae81ff>1000</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>//LOCAL CallUpdate()**
|
||||
</span><span style=color:#75715e></span> ObserverMgt<span style=color:#f92672>.</span>Poll<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking",TempChangeNotification<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>WITH</span> TempChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
<span style=color:#66d9ef>IF</span> "Type of Change" = "Type of Change"::Delete <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span> <span style=color:#66d9ef>ELSE</span> <span style=color:#66d9ef>IF</span> RecRef<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>"Record ID"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span>;
|
||||
Poll<span style=color:#f92672>(</span>TableID : <span style=color:#66d9ef>Integer</span>;<span style=color:#66d9ef>VAR</span> TempChangeNotification : <span style=color:#66d9ef>TEMPORARY</span> <span style=color:#66d9ef>Record</span> "Change Notification"<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>WITH</span> ChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
TempChangeNotification<span style=color:#f92672>.</span>RESET;
|
||||
TempChangeNotification<span style=color:#f92672>.</span>DELETEALL;
|
||||
|
||||
RESET;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Table ID",TableID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Server ID",SERVICEINSTANCEID<span style=color:#f92672>)</span>;
|
||||
SETRANGE<span style=color:#f92672>(</span>"Session ID",SESSIONID<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
TempChangeNotification <span style=color:#f92672>:=</span> ChangeNotification;
|
||||
TempChangeNotification<span style=color:#f92672>.</span>INSERT;
|
||||
MARK<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
MARKEDONLY<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
DELETEALL;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>The final part of this example is an object that calls the functions above. In this example we will use a Page with a PingPong Timer Control to do the polling in (almost) real time. These are the functions on the page:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OnQueryClosePage<span style=color:#f92672>(</span>CloseAction : <span style=color:#66d9ef>Action</span> <span style=color:#66d9ef>None</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>
|
||||
ObserverMgt<span style=color:#f92672>.</span>StopListening<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking"<span style=color:#f92672>)</span>;
|
||||
|
||||
Timer::AddInReady<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> ObserverMgt<span style=color:#f92672>.</span>Listen<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
CurrPage<span style=color:#f92672>.</span>Timer<span style=color:#f92672>.</span>Ping<span style=color:#f92672>(</span><span style=color:#ae81ff>1000</span><span style=color:#f92672>)</span>;
|
||||
|
||||
Timer::Pong<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672></span>CallUpdate;
|
||||
CurrPage<span style=color:#f92672>.</span>Timer<span style=color:#f92672>.</span>Ping<span style=color:#f92672>(</span><span style=color:#ae81ff>1000</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> CallUpdate<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672></span>ObserverMgt<span style=color:#f92672>.</span>Poll<span style=color:#f92672>(</span><span style=color:#66d9ef>DATABASE</span>::"NAV Whiteboard Booking",TempChangeNotification<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>WITH</span> TempChangeNotification <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>REPEAT</span>
|
||||
<span style=color:#66d9ef>IF</span> "Type of Change" = "Type of Change"::Delete <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span> <span style=color:#66d9ef>ELSE</span> <span style=color:#66d9ef>IF</span> RecRef<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>"Record ID"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><h2 id=consequences>Consequences</h2>
|
||||
<p>The PingPong control is only available on the Windows Client, so if you want to use another client you will need to use another solution to Poll for Messages. Therefore this pattern is not always going to be “real time”.</p>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
|
|
@ -393,12 +456,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Currently Active Record :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/currently-active-record/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -249,11 +249,8 @@ ALGuidelines.Dev
|
|||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a>
|
||||
<ul>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#ending-date-problem>Ending Date Problem</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href=#usage>Usage</a>
|
||||
<ul>
|
||||
<li><a href=#1-create-the-view>1. Create the view</a></li>
|
||||
|
|
@ -296,7 +293,7 @@ A side effect is reduced and simplified code, increased performance and a more s
|
|||
<p>The NAV Service Tier receives and throws away data.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id=ending-date-problem>Ending Date Problem</h3>
|
||||
<h2 id=ending-date-problem>Ending Date Problem</h2>
|
||||
<p>Ending Date may introduce some problems of its own.</p>
|
||||
<p>If your design requires to have one and only one active record per key in a dataset, then Ending Date introduces the possibility for overlapping or holes in the timeline.<br>
|
||||
Ending Date creates a dependency between two records. Changing a Starting Date, requires you to update the previous record. Changing the Ending Date requires you to update the next record.<br>
|
||||
|
|
@ -310,20 +307,20 @@ If you add a record in between you will have to update both the before and the a
|
|||
<h3 id=1-create-the-view>1. Create the view</h3>
|
||||
<p>You will need to create the view before you define the Table Object.<br>
|
||||
You will need to create a view for every company in the database.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sql data-lang=sql> <span style=color:#66d9ef>CREATE</span> <span style=color:#66d9ef>VIEW</span> [dbo].[CRONUS$PriceView]
|
||||
<span style=color:#66d9ef>AS</span>
|
||||
<span style=color:#66d9ef>SELECT</span> [Code], [Starting Date], [Price]
|
||||
<span style=color:#66d9ef>FROM</span> dbo.[CRONUS$Price] <span style=color:#66d9ef>AS</span> A
|
||||
<span style=color:#66d9ef>WHERE</span> [Starting Date] <span style=color:#f92672>=</span>
|
||||
(<span style=color:#66d9ef>SELECT</span> <span style=color:#66d9ef>MAX</span>([Starting Date])
|
||||
<span style=color:#66d9ef>FROM</span> dbo.[CRONUS$Price] <span style=color:#66d9ef>AS</span> B
|
||||
<span style=color:#66d9ef>WHERE</span> B.[Code] <span style=color:#f92672>=</span> A.[Code] <span style=color:#66d9ef>AND</span>
|
||||
B.[Starting Date] <span style=color:#f92672><=</span> GETDATE())
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sql data-lang=sql><span style=color:#66d9ef>CREATE</span> <span style=color:#66d9ef>VIEW</span> [dbo].[CRONUS$PriceView]
|
||||
<span style=color:#66d9ef>AS</span>
|
||||
<span style=color:#66d9ef>SELECT</span> [Code], [Starting Date], [Price]
|
||||
<span style=color:#66d9ef>FROM</span> dbo.[CRONUS$Price] <span style=color:#66d9ef>AS</span> A
|
||||
<span style=color:#66d9ef>WHERE</span> [Starting Date] <span style=color:#f92672>=</span>
|
||||
(<span style=color:#66d9ef>SELECT</span> <span style=color:#66d9ef>MAX</span>([Starting Date])
|
||||
<span style=color:#66d9ef>FROM</span> dbo.[CRONUS$Price] <span style=color:#66d9ef>AS</span> B
|
||||
<span style=color:#66d9ef>WHERE</span> B.[Code] <span style=color:#f92672>=</span> A.[Code] <span style=color:#66d9ef>AND</span>
|
||||
B.[Starting Date] <span style=color:#f92672><=</span> GETDATE())
|
||||
</code></pre></div><p>Test the view to ensure that you get the correct result. It is much easier to test now than later.</p>
|
||||
<h3 id=2-create-the-table-object>2. Create the Table object</h3>
|
||||
<p>Remember to set the link table property before you save it.</p>
|
||||
<h3 id=3-implement-the-code>3. Implement the code</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> <span style=color:#66d9ef>IF</span> PriceView<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#75715e>// You have them
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> PriceView<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#75715e>// You have them
|
||||
</span></code></pre></div><h3 id=4-create-a-deployment-codeunit>4. Create a deployment codeunit</h3>
|
||||
<p>Create a SQL Deployment codeunit to manage your views.<br>
|
||||
The codeunit needs to Create or Alter the views for all companies.<br>
|
||||
|
|
@ -392,12 +389,12 @@ The Pattern makes a scalable solution with a predictable performance. The perfor
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Data Migration Façade :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/data-migration-facade/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -276,7 +276,7 @@ ALGuidelines.Dev
|
|||
<h2 id=context>Context:</h2>
|
||||
<p>This pattern is describing how you can migrate data using the Data Migration Façade.</p>
|
||||
<h2 id=problem>Problem:</h2>
|
||||
<p>Writing migration code from an external source, such as a product from a competitor, can be time consuming, as you need to tackle the problems of what to migrate, in which order, exception handling… and can result in code that is fragile due to deep dependencies on the NAV data model (high coupling). Any change to the NAV data model can easily break this code. ****</p>
|
||||
<p>Writing migration code from an external source, such as a product from a competitor, can be time consuming, as you need to tackle the problems of what to migrate, in which order, exception handling… and can result in code that is fragile due to deep dependencies on the NAV data model (high coupling). Any change to the NAV data model can easily break this code.</p>
|
||||
<h2 id=solution>Solution:</h2>
|
||||
<p>The idea of the Data Migration Façade is to provide an API that creates and updates master data and related entities (including transactions) without referencing NAV tables.</p>
|
||||
<p>Additionally, the framework around the Data Migration Façade provides tools for error handling, and a way to integrate the migration in the Data Migration Overview page (page 1799).</p>
|
||||
|
|
@ -301,8 +301,6 @@ ALGuidelines.Dev
|
|||
</li>
|
||||
<li>
|
||||
<p>A page where you can view the status and progress of the migration. It shows one line for each master data entity (item, customer, vendor, general ledger account) that was chosen for migration. You can also stop a migration by choosing the <strong>Stop Migration</strong> action.</p>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<li><strong>Data Migration Overview</strong> (page 1799)</li>
|
||||
</ul>
|
||||
|
|
@ -320,10 +318,10 @@ ALGuidelines.Dev
|
|||
</ul>
|
||||
<p>To initialize and start the data migration, you must call the following procedures:</p>
|
||||
<ul>
|
||||
<li>**“Data Migration Status Façade”.InitStatusLine(‘My Migration Type’,Database::Item,42000,0,Codeunit::“My extension Item migration codeunit”) **<br>
|
||||
<li><strong>“Data Migration Status Façade”.InitStatusLine(‘My Migration Type’,Database::Item,42000,0,Codeunit::“My extension Item migration codeunit”)</strong><br>
|
||||
This deletes existing status lines for migrating Items for ‘My Migration Type’, and initializes a new status line with 0 records migrated out of 42000.</li>
|
||||
</ul>
|
||||
<p>**“Data Migration Façade”.StartMigration(‘My Migration Type’,false) **<br>
|
||||
<p><strong>“Data Migration Façade”.StartMigration(‘My Migration Type’,false)</strong><br>
|
||||
This starts the migration. False means this is not a retry. A re-try is when you migrate one or more records from the <strong>Show Errors</strong> page, which is described later in this document. Retry = true is only used by the <strong>Show Errors</strong> page and should not be used from extensions.</p>
|
||||
<h3 id=usage-without-staging-tables>Usage without staging tables:</h3>
|
||||
<p>The overall workflow is:</p>
|
||||
|
|
@ -340,54 +338,59 @@ This starts the migration. False means this is not a retry. A re-try is when you
|
|||
<li>Loop on all of the records to migrate. You can update the increment of the amount of records migrated: <strong>“Data Migration Status Facade”.IncrementStatusLine(‘My Migration Type’,Database::Item,42).</strong></li>
|
||||
</ol>
|
||||
<p><a href=NoStagingTableNew2.png><img src=NoStagingTableNew2.png alt=" "></a></p>
|
||||
<p>_Figure 1: sequence diagram of the data migration without staging tables _</p>
|
||||
<p><em>Figure 1: sequence diagram of the data migration without staging tables</em></p>
|
||||
<p>The following example shows how to migrate items without staging tables:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> <span style=color:#66d9ef>trigger</span> OnRun<span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
ItemDataMigrationFacade: <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";
|
||||
ItemNumber: <span style=color:#66d9ef>Integer</span>;
|
||||
ItemJson: <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// loop on items retrieved through a web service for example
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>for</span> ItemNumber <span style=color:#f92672>:=</span> <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>to</span> ExternalWebService<span style=color:#f92672>.</span>GetItemCount <span style=color:#66d9ef>do</span> <span style=color:#66d9ef>begin</span>
|
||||
ExternalWebService<span style=color:#f92672>.</span>GetItem<span style=color:#f92672>(</span>ItemNumber,ItemJson<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// create item using the facade
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> ItemDataMigrationFacade<span style=color:#f92672>.</span>CreateItemIfNeeded<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>ItemNumber,ItemJson<span style=color:#f92672>.</span>ItemName1,
|
||||
ItemJson<span style=color:#f92672>.</span>ItemName2,ConvertItemType<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>ItemType<span style=color:#f92672>)) </span><span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>; <span style=color:#75715e>// item already exists
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// set some fields using the facade
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>SetVendorItemNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>VendItemNumber<span style=color:#f92672>)</span>;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetUnitVolume<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>Volume<span style=color:#f92672>)</span>;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetAlternativeItemNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>AltItemNumber<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> ItemJson<span style=color:#f92672>.</span>PrimaryVendor <\> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetVendorNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>PrimaryVendor<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// migrate dependencies
|
||||
</span><span style=color:#75715e></span> MigrateItemUnitOfMeasure<span style=color:#f92672>(</span>ItemDataMigrationFacade,ItemJson<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// modify the item (+run trigger) to save the changes made by setters
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>true<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// update the status in the migration dashboard
|
||||
</span><span style=color:#75715e></span> DataMigrationStatusFacade<span style=color:#f92672>.</span>IncrementMigratedRecordCount<span style=color:#f92672>(</span><span style=color:#e6db74>'My Migration Type'</span>,
|
||||
<span style=color:#66d9ef>Database</span>::Item,<span style=color:#ae81ff>1</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<span style=color:#66d9ef>procedure</span> MigrateItemUnitOfMeasure<span style=color:#f92672>(</span>ItemDataMigrationFacade : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";
|
||||
ItemJson : <span style=color:#66d9ef>Text</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyUnitCodeStagingTable: <span style=color:#66d9ef>Record</span> "My Unit Code Staging Table";
|
||||
DataMigrationStatusFacade: <span style=color:#66d9ef>Codeunit</span> "Data Migration Status Facade";
|
||||
DescriptionToSet: <span style=color:#66d9ef>Text</span>\[<span style=color:#ae81ff>10</span>\];
|
||||
UnitCodeJson: <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#66d9ef>if</span> ItemJson<span style=color:#f92672>.</span>UnitCode = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#75715e>// log an error using the Data migration façade
|
||||
</span><span style=color:#75715e></span> DataMigrationStatusFacade<span style=color:#f92672>.</span>RegisterErrorNoStagingTablesCase<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span><span style=color:#e6db74>'My Migration Type'</span>,<span style=color:#66d9ef>Database</span>::Item,<span style=color:#e6db74>'Unit of measure is empty.'</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> ExternalWebService<span style=color:#f92672>.</span>GetUnitCode<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode,UnitCodeJson<span style=color:#f92672>) </span><span style=color:#66d9ef>then</span>
|
||||
DescriptionToSet <span style=color:#f92672>:=</span> UnitCodeJson<span style=color:#f92672>.</span>Description;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>CreateUnitOfMeasureIfNeeded<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode, DescriptionToSet<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// set the unit of measure on the item
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>SetBaseUnitOfMeasure<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>trigger</span> OnRun<span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
ItemDataMigrationFacade: <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";
|
||||
ItemNumber: <span style=color:#66d9ef>Integer</span>;
|
||||
ItemJson: <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// loop on items retrieved through a web service for example
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>for</span> ItemNumber <span style=color:#f92672>:=</span> <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>to</span> ExternalWebService<span style=color:#f92672>.</span>GetItemCount <span style=color:#66d9ef>do</span> <span style=color:#66d9ef>begin</span>
|
||||
ExternalWebService<span style=color:#f92672>.</span>GetItem<span style=color:#f92672>(</span>ItemNumber,ItemJson<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// create item using the facade
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> ItemDataMigrationFacade<span style=color:#f92672>.</span>CreateItemIfNeeded<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>ItemNumber,ItemJson<span style=color:#f92672>.</span>ItemName1,
|
||||
ItemJson<span style=color:#f92672>.</span>ItemName2,ConvertItemType<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>ItemType<span style=color:#f92672>)) </span><span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>; <span style=color:#75715e>// item already exists
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#75715e>// set some fields using the facade
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>SetVendorItemNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>VendItemNumber<span style=color:#f92672>)</span>;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetUnitVolume<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>Volume<span style=color:#f92672>)</span>;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetAlternativeItemNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>AltItemNumber<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> ItemJson<span style=color:#f92672>.</span>PrimaryVendor <> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>SetVendorNo<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>PrimaryVendor<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// migrate dependencies
|
||||
</span><span style=color:#75715e></span> MigrateItemUnitOfMeasure<span style=color:#f92672>(</span>ItemDataMigrationFacade,ItemJson<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// modify the item (+run trigger) to save the changes made by setters
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>true<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// update the status in the migration dashboard
|
||||
</span><span style=color:#75715e></span> DataMigrationStatusFacade<span style=color:#f92672>.</span>IncrementMigratedRecordCount<span style=color:#f92672>(</span><span style=color:#e6db74>'My Migration Type'</span>,<span style=color:#66d9ef>Database</span>::Item,<span style=color:#ae81ff>1</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
|
||||
<span style=color:#66d9ef>procedure</span> MigrateItemUnitOfMeasure<span style=color:#f92672>(</span>ItemDataMigrationFacade : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade"; ItemJson : <span style=color:#66d9ef>Text</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyUnitCodeStagingTable: <span style=color:#66d9ef>Record</span> "My Unit Code Staging Table";
|
||||
DataMigrationStatusFacade: <span style=color:#66d9ef>Codeunit</span> "Data Migration Status Facade";
|
||||
DescriptionToSet: <span style=color:#66d9ef>Text</span>[<span style=color:#ae81ff>10</span>];
|
||||
UnitCodeJson: <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#66d9ef>if</span> ItemJson<span style=color:#f92672>.</span>UnitCode = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#75715e>// log an error using the Data migration façade
|
||||
</span><span style=color:#75715e></span> DataMigrationStatusFacade<span style=color:#f92672>.</span>RegisterErrorNoStagingTablesCase<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span><span style=color:#e6db74>'My Migration Type'</span>,<span style=color:#66d9ef>Database</span>::Item,<span style=color:#e6db74>'Unit of measure is empty.'</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>if</span> ExternalWebService<span style=color:#f92672>.</span>GetUnitCode<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode,UnitCodeJson<span style=color:#f92672>) </span><span style=color:#66d9ef>then</span>
|
||||
DescriptionToSet <span style=color:#f92672>:=</span> UnitCodeJson<span style=color:#f92672>.</span>Description;
|
||||
ItemDataMigrationFacade<span style=color:#f92672>.</span>CreateUnitOfMeasureIfNeeded<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode, DescriptionToSet<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// set the unit of measure on the item
|
||||
</span><span style=color:#75715e></span> ItemDataMigrationFacade<span style=color:#f92672>.</span>SetBaseUnitOfMeasure<span style=color:#f92672>(</span>ItemJson<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><p><em>Figure 2: Example of Item and Item Unit of Measure migration without staging tables</em></p>
|
||||
<h3 id=usage-with-staging-tables>Usage with staging tables:</h3>
|
||||
<p>The overall workflow is:</p>
|
||||
|
|
@ -409,82 +412,81 @@ This starts the migration. False means this is not a retry. A re-try is when you
|
|||
</li>
|
||||
<li>
|
||||
<p>From the event subscribers, call the façade procedures to create entities and set their field values:</p>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<li><strong>“Item Data Migration Façade”.CreateItemIfNeeded(‘ITEM042’,‘My Item Description’;‘My Item Description 2’;ItemTypeToSet::Inventory)</strong></li>
|
||||
<li><strong>“Item Data Migration Façade”.SetBaseUnitOfMeasure(‘BOX’)</strong></li>
|
||||
<li><strong>“Item Data Migration Façade”.ModifyItem(true)</strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>“Item Data Migration Façade”.SetBaseUnitOfMeasure(‘BOX’)</strong></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>“Item Data Migration Façade”.ModifyItem(true)</strong></p>
|
||||
</li>
|
||||
</ul>
|
||||
<p><a href=StagingTableNew2.png><img src=StagingTableNew2.png alt=" "></a></p>
|
||||
<p><em>Figure 3: Simplified sequence diagram of the data migration with staging tables</em></p>
|
||||
<p>Below is a simplified example showing how to create an item:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> [EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Codeunit</span>, <span style=color:#66d9ef>Codeunit</span>::"Item Data Migration Facade", <span style=color:#e6db74>'OnMigrateItem'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnMigrateItem<span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Sender : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";RecordIdToMigrate : <span style=color:#66d9ef>RecordId</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyItemStagingTable : <span style=color:#66d9ef>Record</span> "My Item Staging Table";
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// handle the event if it targets this extension's staging table
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> RecordIdToMigrate<span style=color:#f92672>.</span>TableNo <\> <span style=color:#66d9ef>Database</span>::"My Item Staging Table" <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>;
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecordIdToMigrate<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// create item using the facade
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> Sender<span style=color:#f92672>.</span>CreateItemIfNeeded<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>ItemNumber,MyItemStagingTable<span style=color:#f92672>.</span>ItemName1,
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>ItemName2,ConvertItemType<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>ItemType<span style=color:#f92672>)) </span><span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>; <span style=color:#75715e>// item already exists
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// set some fields using the facade
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>SetVendorItemNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>VendItemNumber<span style=color:#f92672>)</span>;
|
||||
Sender<span style=color:#f92672>.</span>SetUnitVolume<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>Volume<span style=color:#f92672>)</span>;
|
||||
Sender<span style=color:#f92672>.</span>SetAlternativeItemNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>AltItemNumber<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyItemStagingTable<span style=color:#f92672>.</span>PrimaryVendor <\> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
Sender<span style=color:#f92672>.</span>SetVendorNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>PrimaryVendor<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// modify the item (+run trigger) to save the changes made by setters
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>true<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Codeunit</span>, <span style=color:#66d9ef>Codeunit</span>::"Item Data Migration Facade", <span style=color:#e6db74>'OnMigrateItem'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnMigrateItem<span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Sender : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";RecordIdToMigrate : <span style=color:#66d9ef>RecordId</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyItemStagingTable : <span style=color:#66d9ef>Record</span> "My Item Staging Table";
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// handle the event if it targets this extension's staging table
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> RecordIdToMigrate<span style=color:#f92672>.</span>TableNo <> <span style=color:#66d9ef>Database</span>::"My Item Staging Table" <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>;
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecordIdToMigrate<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// create item using the facade
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> Sender<span style=color:#f92672>.</span>CreateItemIfNeeded<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>ItemNumber,MyItemStagingTable<span style=color:#f92672>.</span>ItemName1,
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>ItemName2,ConvertItemType<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>ItemType<span style=color:#f92672>)) </span><span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>; <span style=color:#75715e>// item already exists
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#75715e>// set some fields using the facade
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>SetVendorItemNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>VendItemNumber<span style=color:#f92672>)</span>;
|
||||
Sender<span style=color:#f92672>.</span>SetUnitVolume<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>Volume<span style=color:#f92672>)</span>;
|
||||
Sender<span style=color:#f92672>.</span>SetAlternativeItemNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>AltItemNumber<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyItemStagingTable<span style=color:#f92672>.</span>PrimaryVendor <> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
Sender<span style=color:#f92672>.</span>SetVendorNo<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>PrimaryVendor<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// modify the item (+run trigger) to save the changes made by setters
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>true<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><p><em>Figure 4: Example of event subscriber for Item migration</em></p>
|
||||
<p>Below is another example showing how to use additional events to set fields that reference other tables, here the unit of measure:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> [EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Codeunit</span>, <span style=color:#66d9ef>Codeunit</span>::"Item Data Migration Facade", <span style=color:#e6db74>'OnMigrateItemUnitOfMeasure'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnMigrateItemUnitOfMeasure<span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Sender : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";RecordIdToMigrate : <span style=color:#66d9ef>RecordId</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyItemStagingTable : <span style=color:#66d9ef>Record</span> "My Item Staging Table";
|
||||
MyUnitCodeStagingTable : <span style=color:#66d9ef>Record</span> "My Unit Code Staging Table";
|
||||
DescriptionToSet: <span style=color:#66d9ef>Text</span>[<span style=color:#ae81ff>10</span>];
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// handle the event if it targets this extension's staging table
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> RecordIdToMigrate<span style=color:#f92672>.</span>TableNo <\> <span style=color:#66d9ef>Database</span>::"My Item Staging Table" <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>;
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecordIdToMigrate<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyItemStagingTable<span style=color:#f92672>.</span>UnitCode = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
error<span style=color:#f92672>(</span><span style=color:#e6db74>'Unit of measure is empty.'</span><span style=color:#f92672>)</span>;
|
||||
MyUnitCodeStagingTable<span style=color:#f92672>.</span>SetRange<span style=color:#f92672>(</span>UnitCode,MyItemStagingTable<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyUnitCodeStagingTable<span style=color:#f92672>.</span>FindFirst <span style=color:#66d9ef>then</span>
|
||||
DescriptionToSet <span style=color:#f92672>:=</span> MyUnitCodeStagingTable<span style=color:#f92672>.</span>Description;
|
||||
<span style=color:#75715e>// create the unit of measure through the facade
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>CreateUnitOfMeasureIfNeeded<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>UnitCode, DescriptionToSet<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// set the unit of measure on the item
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>SetBaseUnitOfMeasure<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#75715e>// modify the item to save the changes made by setter
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>false<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Codeunit</span>, <span style=color:#66d9ef>Codeunit</span>::"Item Data Migration Facade", <span style=color:#e6db74>'OnMigrateItemUnitOfMeasure'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnMigrateItemUnitOfMeasure<span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Sender : <span style=color:#66d9ef>Codeunit</span> "Item Data Migration Facade";RecordIdToMigrate : <span style=color:#66d9ef>RecordId</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>var</span>
|
||||
MyItemStagingTable : <span style=color:#66d9ef>Record</span> "My Item Staging Table";
|
||||
MyUnitCodeStagingTable : <span style=color:#66d9ef>Record</span> "My Unit Code Staging Table";
|
||||
DescriptionToSet: <span style=color:#66d9ef>Text</span>[<span style=color:#ae81ff>10</span>];
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// handle the event if it targets this extension's staging table
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> RecordIdToMigrate<span style=color:#f92672>.</span>TableNo <> <span style=color:#66d9ef>Database</span>::"My Item Staging Table" <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>;
|
||||
|
||||
MyItemStagingTable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecordIdToMigrate<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyItemStagingTable<span style=color:#f92672>.</span>UnitCode = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
error<span style=color:#f92672>(</span><span style=color:#e6db74>'Unit of measure is empty.'</span><span style=color:#f92672>)</span>;
|
||||
MyUnitCodeStagingTable<span style=color:#f92672>.</span>SetRange<span style=color:#f92672>(</span>UnitCode,MyItemStagingTable<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>if</span> MyUnitCodeStagingTable<span style=color:#f92672>.</span>FindFirst <span style=color:#66d9ef>then</span>
|
||||
DescriptionToSet <span style=color:#f92672>:=</span> MyUnitCodeStagingTable<span style=color:#f92672>.</span>Description;
|
||||
|
||||
<span style=color:#75715e>// create the unit of measure through the facade
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>CreateUnitOfMeasureIfNeeded<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>UnitCode, DescriptionToSet<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// set the unit of measure on the item
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>SetBaseUnitOfMeasure<span style=color:#f92672>(</span>MyItemStagingTable<span style=color:#f92672>.</span>UnitCode<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// modify the item to save the changes made by setter
|
||||
</span><span style=color:#75715e></span> Sender<span style=color:#f92672>.</span>ModifyItem<span style=color:#f92672>(</span>false<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><p><em>Figure 5: Example of event subscriber for Item Unit of Measure migration</em></p>
|
||||
<h3 id=combining-both-approaches>Combining both approaches:</h3>
|
||||
<p>If you want to migrate additional entities, the **Data Migration **framework lets you initialize the migration with entities other than master data. In this case, the <strong>Data Migration Overview</strong> page will show additional lines. Item, vendor, customer, an general ledger accounts are migrated with an event driven approach, and the additional entities are migrated by calling an extension codeunit <strong>OnRun</strong> method.</p>
|
||||
<p>If you want to migrate additional entities, the <strong>Data Migration</strong> framework lets you initialize the migration with entities other than master data. In this case, the <strong>Data Migration Overview</strong> page will show additional lines. Item, vendor, customer, an general ledger accounts are migrated with an event driven approach, and the additional entities are migrated by calling an extension codeunit <strong>OnRun</strong> method.</p>
|
||||
<h2 id=error-handling-with-staging-tables>Error handling with staging tables:</h2>
|
||||
<p>The migration starts by calling <strong>RUN</strong> on the façade codeunit. Errors thrown during the call are captured by <strong>GETLASTERRORTEXT</strong> and displayed when you choose the <strong>Show Errors</strong> action on the <strong>Data Migration Overview</strong> page.</p>
|
||||
<p><a href=errorhandling1.png><img src=errorhandling1.png alt=" "></a></p>
|
||||
<p><em>Figure 6: List of errors shown when clicking <strong>Show Errors</strong> on the <strong>Data Migration Overview</strong> page</em></p>
|
||||
<p>__</p>
|
||||
<p>The <strong>Edit Record</strong> action opens a view of the staging table, where you can edit fields to fix errors. Figure 4 shows an example of a page for the vendor staging table in a migration from C5.</p>
|
||||
<p><a href=errorhandling2.png><img src=errorhandling2.png alt=" "></a></p>
|
||||
<p><em>Figure 7: Edit a staging table record</em></p>
|
||||
<p>__</p>
|
||||
<p>The <strong>Staging Table ID</strong> determines the page to open, so it is important that the page ID is equal to the <strong>Staging Table ID</strong>, at least for the master data staging tables, for example, for<strong>G/L Accounts, Items, Customers</strong> and <strong>Vendor</strong>. You should ensure that pages to edit related entities are linked on this page by means of new actions. For example, Figure 4 uses the <strong>C5 Purchaser</strong> action.</p>
|
||||
<p>The <strong>Staging Table ID</strong> determines the page to open, so it is important that the page ID is equal to the <strong>Staging Table ID</strong>, at least for the master data staging tables, for example, for <strong>G/L Accounts, Items, Customers</strong> and <strong>Vendor</strong>. You should ensure that pages to edit related entities are linked on this page by means of new actions. For example, Figure 4 uses the <strong>C5 Purchaser</strong> action.</p>
|
||||
<p>After you fix the staging table record, you can choose the <strong>Migrate</strong> action to mark the selected records as records to retry, and then run <strong>StartMigration</strong> with the <strong>Retry</strong> flag set to true. This is the only place where the retry flag should be set to true in the <strong>StartMigration</strong> procedure.</p>
|
||||
<p>Error handling without staging tables</p>
|
||||
<p>When migrating data without staging tables, errors can be registered manually by the extension using <strong>DataMigrationStatusFacade.RegisterErrorNoStagingTablesCase</strong>. Otherwise they can be registered automatically if the codeunits fail when called on their <strong>OnRun</strong> procedure.</p>
|
||||
|
|
@ -544,12 +546,12 @@ This starts the migration. False means this is not a retry. A re-try is when you
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Discovery Event :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/discovery-event/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -269,12 +269,16 @@ ALGuidelines.Dev
|
|||
<h1 id=usage>Usage</h1>
|
||||
<p>The pattern is most easily described when you look at an example. This example is an actual usage of the pattern within the application, in page <strong>Service Connections.</strong></p>
|
||||
<p><a href=ServiceConnections.jpg><img src=ServiceConnections.jpg alt=" "></a></p>
|
||||
<p>The goal of this functionality is to:<br>
|
||||
• List all the different connections to external services,<br>
|
||||
• Have a central place to navigate to the corresponding setup of the service.</p>
|
||||
<p>The functionality (<strong>Service Connections</strong>) itself, is not aware of the state nor setup nor any context of all the different services in the list. All it does is:<br>
|
||||
• It raises an event as an opportunity for all services within the NAV application to subscribe to,<br>
|
||||
• It has a public function <strong>InsertServiceConnection</strong> that the subscribers can use to register itself at the Service Connection.</p>
|
||||
<p>The goal of this functionality is to:</p>
|
||||
<ul>
|
||||
<li>List all the different connections to external services,</li>
|
||||
<li>Have a central place to navigate to the corresponding setup of the service.</li>
|
||||
</ul>
|
||||
<p>The functionality (<strong>Service Connections</strong>) itself, is not aware of the state nor setup nor any context of all the different services in the list. All it does is:</p>
|
||||
<ul>
|
||||
<li>It raises an event as an opportunity for all services within the NAV application to subscribe to,</li>
|
||||
<li>It has a public function <strong>InsertServiceConnection</strong> that the subscribers can use to register itself at the Service Connection.</li>
|
||||
</ul>
|
||||
<p>The event <strong>OnRegisterServiceConnection</strong> is raised when the page (1279 - <strong>Service Connections</strong>) is opened.</p>
|
||||
<p>One example of a subscription is the SMTP setup. In Codeunit 400 you’ll find the subscriber function <strong>HandleSMTPRegisterServiceConnection</strong> which subscribes to this discovery event, and calls the <strong>InsertServiceConnection</strong> to register itself.</p>
|
||||
<h1 id=description>Description</h1>
|
||||
|
|
@ -311,12 +315,12 @@ You see I can use the “sender” as a normal Record-variable. I access
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Document :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/document/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -308,7 +308,7 @@ ALGuidelines.Dev
|
|||
<li>Click Finish to close the wizard</li>
|
||||
</ul>
|
||||
<p>Then simply add your subpage as new line in the designer, and adjust the property “SubFormPerLink” with “Document No.=FIELD(No.)” to link header and lines :</p>
|
||||
<p>**<a href=2086.Design-Pattern-Document-SubPage-Properties.png><img src=2086.Design-Pattern-Document-SubPage-Properties.png alt=" "></a>**</p>
|
||||
<p><a href=2086.Design-Pattern-Document-SubPage-Properties.png><img src=2086.Design-Pattern-Document-SubPage-Properties.png alt=" "></a></p>
|
||||
<p><strong>Page “Document List”:</strong> Use the Page wizard to create a List page based on the Document table and add fields, FactBox (RecordLinks, Notes…), etc.</p>
|
||||
<p>Once created:</p>
|
||||
<ul>
|
||||
|
|
@ -348,12 +348,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Easy Update Of Setup Or Supplementary Information :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/easy-update-of-setup-or-supplementary-information/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -271,37 +271,34 @@ ALGuidelines.Dev
|
|||
<h2 id=usage>Usage</h2>
|
||||
<p>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.</p>
|
||||
<p>Call the code. For example:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL><span style=color:#66d9ef>Local</span> IsXAvailable : <span style=color:#66d9ef>Boolean</span>
|
||||
<span style=color:#66d9ef>If</span> <span style=color:#66d9ef>field</span> X <\> <span style=color:#e6db74>''</span> <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>Exit</span><span style=color:#f92672>(</span>True<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>Exit</span><span style=color:#f92672>(</span>false<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>VerifyAndSetX
|
||||
<span style=color:#66d9ef>If</span> IsXAvailable <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>Exit</span>;
|
||||
<span style=color:#66d9ef>If</span> Confirm<span style=color:#f92672>(</span><span style=color:#e6db74>'Field X is missing a value. Do you want to update it now?'</span><span style=color:#f92672>) </span><span style=color:#66d9ef>then</span>
|
||||
Open the card <span style=color:#66d9ef>page</span> <span style=color:#66d9ef>in</span> edit mode
|
||||
<pre tabindex=0><code>Local IsXAvailable : Boolean
|
||||
If field X <> '' then
|
||||
Exit(True)
|
||||
Exit(false)
|
||||
|
||||
<span style=color:#66d9ef>If</span> <span style=color:#f92672>not</span> IsXAvailable <span style=color:#66d9ef>then</span>
|
||||
Error<span style=color:#f92672>(</span><span style=color:#66d9ef>Field</span> X is missing a <span style=color:#66d9ef>value</span><span style=color:#f92672>. </span>Please correct it<span style=color:#f92672>.)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>The calling <span style=color:#66d9ef>code</span>
|
||||
VerifyAndSetX
|
||||
If IsXAvailable then
|
||||
Exit;
|
||||
If Confirm('Field X is missing a value. Do you want to update it now?') then
|
||||
Open the card page in edit mode
|
||||
|
||||
If not IsXAvailable then
|
||||
Error(Field X is missing a value. Please correct it.)
|
||||
</code></pre><p>The calling code</p>
|
||||
<pre tabindex=0><code>..
|
||||
|
||||
<span style=color:#f92672>..
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>SetupTable<span style=color:#f92672>.</span>VerifyAndSetX
|
||||
SetupTable.VerifyAndSetX
|
||||
|
||||
<span style=color:#f92672>..
|
||||
</span></code></pre></div><h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<hr>
|
||||
..
|
||||
</code></pre><h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<p>In the <strong>Sales & Receivables Setup</strong> table (311) for the DK version, the following procedures have been added:</p>
|
||||
<p>Local Procedure IsOIOUBLPathAvailable(…)</p>
|
||||
<p>Procedure VerifyAndSetOIOUBLPath(…)</p>
|
||||
<p>The code in the <strong>Sales & Receivables Setup</strong> table can now be called directly from the related processing codeunit, such as the <strong>Sales-Post + Print</strong> codeunit (82).</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>Local</span> <span style=color:#66d9ef>Procedure</span> IsOIOUBLPathAvailable<span style=color:#f92672>(...)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>Procedure</span> VerifyAndSetOIOUBLPath<span style=color:#f92672>(...)
|
||||
</span></code></pre></div><p>The code in the <strong>Sales & Receivables Setup</strong> table can now be called directly from the related processing codeunit, such as the <strong>Sales-Post + Print</strong> codeunit (82).</p>
|
||||
<p>Were the code is called:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL><span style=color:#66d9ef>IF</span> <span style=color:#f92672>(</span>"EAN No." <\> <span style=color:#e6db74>''</span><span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
|
||||
SalesSetup<span style=color:#f92672>.</span>VerifyAndSetOIOUBLPathSetup<span style=color:#f92672>(</span>SalesHeader<span style=color:#f92672>.</span>"Document Type"<span style=color:#f92672>)</span>;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> <span style=color:#f92672>(</span>"EAN No." <> <span style=color:#e6db74>''</span><span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
SalesSetup<span style=color:#f92672>.</span>VerifyAndSetOIOUBLPathSetup<span style=color:#f92672>(</span>SalesHeader<span style=color:#f92672>.</span>"Document Type"<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>If the setup is not updated properly, the user is prompted to update it as follows.</p>
|
||||
<p><a href=0654.easy-update-1.png><img src=0654.easy-update-1.png alt=" "></a></p>
|
||||
<p>Choosing <strong>Yes</strong> opens the related setup page.</p>
|
||||
|
|
@ -332,12 +329,12 @@ SalesSetup<span style=color:#f92672>.</span>VerifyAndSetOIOUBLPathSetup<span sty
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Error Message Processing :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/error-message-processing/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -263,7 +263,7 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Error Message Processing</h1>
|
||||
<p><em>By Jesper Schulz at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>Note: This pattern describes new functionality which makes it possible to generalize the <a href=/nav/w/designpatterns/124.journal-error-processing.aspx>Journal Error Processing</a> pattern.</p>
|
||||
<p>Note: This pattern describes new functionality which makes it possible to generalize the <a href=/navpatterns/1-patterns/journal-error-processing/>Journal Error Processing</a> pattern.</p>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>Missing, invalid or incomplete data is a common issue during data processing in NAV. This article describes how to collect all error messages during processing using the error message component and present them to the user in a unified way, which enables the user to correct the errors efficiently. By leveraging the integrated error message logging functions, you can log a message with a single line of code and present it to the user with another one-liner.</p>
|
||||
<h2 id=description>Description</h2>
|
||||
|
|
@ -275,7 +275,7 @@ ALGuidelines.Dev
|
|||
<p>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.</p>
|
||||
<p>The example below comes from a Mexican localization, where the user has to export financial balances and transactions into an XML file for government audit purposes. In order to generate valid files, some mandatory data needs to be entered in the system. By leveraging the error message component, the user will be presented with the following page, if missing or invalid data was discovered:</p>
|
||||
<p><a href=image001.png><img src=image001.png alt=" "></a></p>
|
||||
<p>By clicking on the error message, the user will be presented with the entity, where the invalid / missing data should be corrected / added. This is done by applying the related pattern <a href=/nav/w/designpatterns/104.easy-update-of-setup-or-supplementary-information.aspx>Easy Update of Setup or Supplementary Information</a>.</p>
|
||||
<p>By clicking on the error message, the user will be presented with the entity, where the invalid / missing data should be corrected / added. This is done by applying the related pattern <a href=/navpatterns/1-patterns/easy-update-of-setup-or-supplementary-information/>Easy Update of Setup or Supplementary Information</a>.</p>
|
||||
<p><a href=image003.png><img src=image003.png alt=" "></a></p>
|
||||
<h2 id=usage>Usage</h2>
|
||||
<p>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:</p>
|
||||
|
|
@ -298,13 +298,14 @@ ALGuidelines.Dev
|
|||
<p>When the processing is complete, you can check if any error messages of type “Error” were logged by calling the <strong>HasErrors</strong> function and you can show the list or error messages by calling the <strong>ShowErrorMessages</strong> function. You can also integrate the error messages list as a FactBox, but that is not part of this example.</p>
|
||||
<h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<p>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.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL> <span style=color:#66d9ef>PROCEDURE</span> ExportChartOfAccounts@<span style=color:#ae81ff>1</span><span style=color:#f92672>(</span>Year@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Integer</span>;Month@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
TempErrorMessage@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>TEMPORARY</span> <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>700</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-AL data-lang=AL><span style=color:#66d9ef>PROCEDURE</span> ExportChartOfAccounts@<span style=color:#ae81ff>1</span><span style=color:#f92672>(</span>Year@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Integer</span>;Month@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
TempErrorMessage@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>TEMPORARY</span> <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>700</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
TempErrorMessage<span style=color:#f92672>.</span>ClearLog; <span style=color:#75715e>// only necessary if variable is global
|
||||
</span><span style=color:#75715e></span> <span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span>CreateXMLHeader<span style=color:#f92672>(</span>Document,RootNode,CatalogoNodeTxt,Namespace,Year,Month,<span style=color:#e6db74>'1.1'</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> GLAccount<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
TempErrorMessage<span style=color:#f92672>.</span>LogIfEmpty <span style=color:#f92672>(</span>GLAccount,GLAccount<span style=color:#f92672>.</span>FIELDNO<span style=color:#f92672>(</span>Name<span style=color:#f92672>)</span>,TempErrorMessage<span style=color:#f92672>.</span>"Message Type"::Error<span style=color:#f92672>)</span>;
|
||||
|
|
@ -318,18 +319,18 @@ ALGuidelines.Dev
|
|||
GLAccount<span style=color:#f92672>.</span>"Debit/Credit"::Credit:
|
||||
XMLDOMManagement<span style=color:#f92672>.</span>AddAttribute<span style=color:#f92672>(</span>Node,<span style=color:#e6db74>'Natur'</span>,<span style=color:#e6db74>'A'</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>ELSE</span>
|
||||
TempErrorMessage<span style=color:#f92672>.</span>LogMessage<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span>GLAccount,GLAccount<span style=color:#f92672>.</span>FIELDNO<span style=color:#f92672>(</span>"Debit/Credit"<span style=color:#f92672>)</span>,TempErrorMessage<span style=color:#f92672>.</span>"Message Type"::Error,
|
||||
STRSUBSTNO<span style=color:#f92672>(</span>GLAccountTypeErr,GLAccount<span style=color:#f92672>.</span>"Debit/Credit",GLAccount<span style=color:#f92672>.</span><span style=color:#66d9ef>RECORDID</span><span style=color:#f92672>))</span>;
|
||||
TempErrorMessage<span style=color:#f92672>.</span>LogMessage<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span>GLAccount,GLAccount<span style=color:#f92672>.</span>FIELDNO<span style=color:#f92672>(</span>"Debit/Credit"<span style=color:#f92672>)</span>,TempErrorMessage<span style=color:#f92672>.</span>"Message Type"::Error,
|
||||
STRSUBSTNO<span style=color:#f92672>(</span>GLAccountTypeErr,GLAccount<span style=color:#f92672>.</span>"Debit/Credit",GLAccount<span style=color:#f92672>.</span><span style=color:#66d9ef>RECORDID</span><span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> GLAccount<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span> <span style=color:#66d9ef>ELSE</span>
|
||||
TempErrorMessage<span style=color:#f92672>.</span>LogSimpleMessage<span style=color:#f92672>(</span>TempErrorMessage<span style=color:#f92672>.</span>"Message Type"::Error,NoSATAccountDefinedErr<span style=color:#f92672>)</span>;
|
||||
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> TempErrorMessage<span style=color:#f92672>.</span>HasErrors<span style=color:#f92672>(</span>TRUE<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
SaveXMLToClient<span style=color:#f92672>(</span>Document,Year,Month,<span style=color:#e6db74>'CT'</span><span style=color:#f92672>)</span>;
|
||||
TempErrorMessage<span style=color:#f92672>.</span>ShowErrorMessages<span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
TempErrorMessage<span style=color:#f92672>.</span>ShowErrorMessages<span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>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.</p>
|
||||
<h2 id=ideas-for-improvement>Ideas for improvement</h2>
|
||||
<p>By using this easy to use component, we have the possibility to extend this functionality going forward. A nice addition to the error message component would be the possibility to log the error messages persistently in a grouped manner, thereby allowing 3rd parties to see the issues the users bump into the most, or allowing 3rd parties to get an detailed insight into what happened, thereby enabling them to provide better support.</p>
|
||||
|
|
@ -345,12 +346,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Extending the Role Center Headlines :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/extending-the-role-center-headlines/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -266,19 +266,14 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Extending the Role Center Headlines</h1>
|
||||
<p><em>By David Bastide at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>_<a href=3733.logo.png><img src=3733.logo.png alt=" "></a>_</p>
|
||||
<p>__</p>
|
||||
<p><a href=3733.logo.png><img src=3733.logo.png alt=" "></a></p>
|
||||
<h2 id=context>Context</h2>
|
||||
<p>Headlines are designed as a page of type HeadlinePart containing at least one text field. The part is added to the top of Role Center pages.<br>
|
||||
This document provides an elegant and extensible pattern about how to extend the Role Center headlines to add your own business headlines based on your data, and display them only if relevant.</p>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>The Dynamics 365 Business Central release (April 2018) introduces a new HeadlinePart page type. This page type defines a page that rotates a display of several headlines after another, in the web client. A user can also click to switch to another headline. Headlines can also include a drilldown action that will be invoked when the user clicks the headline Text of the payload can be emphasized.<br>
|
||||
Headlines are divided in 2 parts: the qualifier, and the payload as you can see in the figure below.<br>
|
||||
_<br>
|
||||
_</p>
|
||||
Headlines are divided in 2 parts: the qualifier, and the payload as you can see in the figure below.</p>
|
||||
<p><a href=Headline.png><img src=Headline.png alt=" "></a></p>
|
||||
<p>< –[if gte mso 9]>< [endif]–>< –[if gte mso 9]>< [endif]–>< –[if gte mso 9]>< [endif]–>< –[if gte mso 10]>
|
||||
< [endif]–></p>
|
||||
<p><em>Figure 1: Qualifier, Payload and emphasized text.</em></p>
|
||||
<h2 id=usage>Usage</h2>
|
||||
<p>A page part has been added to each major Role Center:</p>
|
||||
|
|
@ -310,84 +305,79 @@ If no headline is added on these pages, fallback headlines will be displayed.</p
|
|||
</ul>
|
||||
<h3 id=examples>Examples:</h3>
|
||||
<h4 id=1-extending-the-page-with-a-new-headline>1. Extending the page with a new headline:</h4>
|
||||
<pre><code>group(LargestSale)
|
||||
{
|
||||
Visible = LargestSaleVisible;
|
||||
ShowCaption=false;
|
||||
Editable=false;
|
||||
|
||||
field(LargestSaleText;LargestSaleText)
|
||||
{
|
||||
ApplicationArea = Basic, Suite;
|
||||
DrillDown=true;
|
||||
|
||||
trigger OnDrillDown()
|
||||
var
|
||||
EssentialBusHeadlineMgt: Codeunit "Essential Bus. Headline Mgt.";
|
||||
begin
|
||||
EssentialBusHeadlineMgt.OnDrillDownLargestSale();
|
||||
end;
|
||||
}
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>group</span><span style=color:#f92672>(</span>LargestSale<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span>{
|
||||
Visible = LargestSaleVisible;
|
||||
ShowCaption=false;
|
||||
Editable=false;
|
||||
|
||||
<span style=color:#66d9ef>field</span><span style=color:#f92672>(</span>LargestSaleText;LargestSaleText<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span>{
|
||||
ApplicationArea = Basic, Suite;
|
||||
DrillDown=true;
|
||||
|
||||
<span style=color:#66d9ef>trigger</span> OnDrillDown<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>var</span>
|
||||
EssentialBusHeadlineMgt: <span style=color:#66d9ef>Codeunit</span> "Essential Bus. Headline Mgt.";
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
EssentialBusHeadlineMgt<span style=color:#f92672>.</span>OnDrillDownLargestSale<span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id=heading></h4>
|
||||
<h4 id=2-subscribing-to-the-oncomputeheadlines-event-and-computing-headlines>2. Subscribing to the OnComputeHeadlines event, and computing headlines</h4>
|
||||
<pre><code>\[EventSubscriber(ObjectType::Codeunit, Codeunit::"Headline RC Business Manager", 'OnComputeHeadlines', '', true, true)\]
|
||||
procedure OnComputeHeadlinesBusinessManager()
|
||||
begin
|
||||
// \[...\] compute headline, and init the EssentialBusinessHeadline record
|
||||
if not ShowHeadline then
|
||||
exit; // not enough data to compute headline
|
||||
if not HeadlineManagement.GetHeadlineText(
|
||||
'Insight from last week',
|
||||
StrSubstNo('The largest posted sales invoice was for %1',
|
||||
HeadlineManagement.Emphasize(Format(CustomerLedgerEntry.Amount, 0, TypeHelper.GetAmountFormatWithUserLocale('$'))))
|
||||
EssentialBusinessHeadline."Headline Text")
|
||||
then
|
||||
exit;
|
||||
EssentialBusinessHeadline.Validate("Headline Visible", true);
|
||||
EssentialBusinessHeadline.Modify();
|
||||
end;
|
||||
</code></pre>
|
||||
<h4 id=heading-1></h4>
|
||||
<h4 id=3-subscribing-to-the-onisanyextensionheadlinevisible-event>3. Subscribing to the OnIsAnyExtensionHeadlineVisible event</h4>
|
||||
<pre><code>\[EventSubscriber(ObjectType::Page, Page::"Headline RC Business Manager", 'OnIsAnyExtensionHeadlineVisible', '', true, true)\]
|
||||
procedure OnIsAnyExtensionHeadlineVisible(var ExtensionHeadlinesVisible: Boolean)
|
||||
var
|
||||
EssentialBusinessHeadline: Record "Essential Business Headline";
|
||||
AtLeastOneHeadlineVisible: Boolean;
|
||||
begin
|
||||
EssentialBusinessHeadline.SetRange("Headline Visible", true);
|
||||
EssentialBusinessHeadline.SetFilter("Headline Name",'%1|%2|%3|%4|%5',
|
||||
EssentialBusinessHeadline."Headline Name"::LargestOrder,
|
||||
EssentialBusinessHeadline."Headline Name"::LargestSale,
|
||||
EssentialBusinessHeadline."Headline Name"::BusiestResource,
|
||||
EssentialBusinessHeadline."Headline Name"::MostPopularItem,
|
||||
EssentialBusinessHeadline."Headline Name"::SalesIncrease,
|
||||
EssentialBusinessHeadline."Headline Name"::TopCustomer);
|
||||
AtLeastOneHeadlineVisible := not EssentialBusinessHeadline.IsEmpty();
|
||||
// only modify the var if this extension is making some headlines visible, setting to false could override some other extensions setting the value to true
|
||||
if AtLeastOneHeadlineVisible then
|
||||
ExtensionHeadlinesVisible := true;
|
||||
end;
|
||||
</code></pre>
|
||||
<h4 id=heading-2></h4>
|
||||
</code></pre></div><h4 id=2-subscribing-to-the-oncomputeheadlines-event-and-computing-headlines>2. Subscribing to the OnComputeHeadlines event, and computing headlines</h4>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Codeunit</span>, <span style=color:#66d9ef>Codeunit</span>::"Headline RC Business Manager", <span style=color:#e6db74>'OnComputeHeadlines'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnComputeHeadlinesBusinessManager<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>begin</span>
|
||||
<span style=color:#75715e>// [...] compute headline, and init the EssentialBusinessHeadline record
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> ShowHeadline <span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>; <span style=color:#75715e>// not enough data to compute headline
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> HeadlineManagement<span style=color:#f92672>.</span>GetHeadlineText<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span><span style=color:#e6db74>'Insight from last week'</span>,
|
||||
StrSubstNo<span style=color:#f92672>(</span><span style=color:#e6db74>'The largest posted sales invoice was for %1'</span>,
|
||||
HeadlineManagement<span style=color:#f92672>.</span>Emphasize<span style=color:#f92672>(</span>Format<span style=color:#f92672>(</span>CustomerLedgerEntry<span style=color:#f92672>.</span>Amount, <span style=color:#ae81ff>0</span>, TypeHelper<span style=color:#f92672>.</span>GetAmountFormatWithUserLocale<span style=color:#f92672>(</span><span style=color:#e6db74>'$'</span><span style=color:#f92672>))))
|
||||
</span><span style=color:#f92672> </span>EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Text"<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>then</span>
|
||||
<span style=color:#66d9ef>exit</span>;
|
||||
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>Validate<span style=color:#f92672>(</span>"Headline Visible", true<span style=color:#f92672>)</span>;
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span><span style=color:#66d9ef>Modify</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><h4 id=3-subscribing-to-the-onisanyextensionheadlinevisible-event>3. Subscribing to the OnIsAnyExtensionHeadlineVisible event</h4>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[EventSubscriber<span style=color:#f92672>(</span><span style=color:#66d9ef>ObjectType</span>::<span style=color:#66d9ef>Page</span>, <span style=color:#66d9ef>Page</span>::"Headline RC Business Manager", <span style=color:#e6db74>'OnIsAnyExtensionHeadlineVisible'</span>, <span style=color:#e6db74>''</span>, true, true<span style=color:#f92672>)</span>]
|
||||
<span style=color:#66d9ef>procedure</span> OnIsAnyExtensionHeadlineVisible<span style=color:#f92672>(</span><span style=color:#66d9ef>var</span> ExtensionHeadlinesVisible: <span style=color:#66d9ef>Boolean</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>var</span>
|
||||
EssentialBusinessHeadline: <span style=color:#66d9ef>Record</span> "Essential Business Headline";
|
||||
AtLeastOneHeadlineVisible: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>begin</span>
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>SetRange<span style=color:#f92672>(</span>"Headline Visible", true<span style=color:#f92672>)</span>;
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>SetFilter<span style=color:#f92672>(</span>"Headline Name",<span style=color:#e6db74>'%1|%2|%3|%4|%5'</span>,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::LargestOrder,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::LargestSale,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::BusiestResource,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::MostPopularItem,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::SalesIncrease,
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::TopCustomer<span style=color:#f92672>)</span>;
|
||||
|
||||
AtLeastOneHeadlineVisible <span style=color:#f92672>:=</span> <span style=color:#f92672>not</span> EssentialBusinessHeadline<span style=color:#f92672>.</span>IsEmpty<span style=color:#f92672>()</span>;
|
||||
<span style=color:#75715e>// only modify the var if this extension is making some headlines visible, setting to false could override some other extensions setting the value to true
|
||||
</span><span style=color:#75715e></span> <span style=color:#66d9ef>if</span> AtLeastOneHeadlineVisible <span style=color:#66d9ef>then</span>
|
||||
ExtensionHeadlinesVisible <span style=color:#f92672>:=</span> true;
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><h4 id=heading></h4>
|
||||
<h4 id=4-setting-the-headline-text-on-the-page>4. Setting the headline text on the page</h4>
|
||||
<pre><code>trigger OnAfterGetRecord()
|
||||
begin
|
||||
EssentialBusinessHeadline.GetHeadline(EssentialBusinessHeadline."Headline Name"::LargestSale);
|
||||
LargestSaleVisible := EssentialBusinessHeadline."Headline Visible";
|
||||
LargestSaleText := EssentialBusinessHeadline."Headline Text";
|
||||
end;
|
||||
</code></pre>
|
||||
<p><a href=0724.Headline-sequence-diagram-v2.png><img src=0724.Headline-sequence-diagram-v2.png alt=" "></a></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>trigger</span> OnAfterGetRecord<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>begin</span>
|
||||
EssentialBusinessHeadline<span style=color:#f92672>.</span>GetHeadline<span style=color:#f92672>(</span>EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Name"::LargestSale<span style=color:#f92672>)</span>;
|
||||
LargestSaleVisible <span style=color:#f92672>:=</span> EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Visible";
|
||||
LargestSaleText <span style=color:#f92672>:=</span> EssentialBusinessHeadline<span style=color:#f92672>.</span>"Headline Text";
|
||||
<span style=color:#66d9ef>end</span>;
|
||||
</code></pre></div><p><a href=0724.Headline-sequence-diagram-v2.png><img src=0724.Headline-sequence-diagram-v2.png alt=" "></a></p>
|
||||
<p><em>Figure 2: Sequence diagram of headline usage</em></p>
|
||||
<h2 id=usages-in-nav>Usages in NAV:</h2>
|
||||
<ul>
|
||||
<li>Essential Business Headlines extension</li>
|
||||
</ul>
|
||||
<p>< –[if gte mso 9]>< [endif]–>< –[if gte mso 9]>< [endif]–>< –[if gte mso 9]>< [endif]–>< –[if supportAnnotations]–>< –[endif]–>< –[if gte mso 10]>
|
||||
< [endif]–></p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -400,12 +390,12 @@ end;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Feature Localization For Data Structures :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/feature-localization-for-data-structures/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -401,7 +401,7 @@ PrevVendorBillLine <span style=color:#f92672>:=</span> VendorBillLine;
|
|||
|
||||
VendorBillLine<span style=color:#f92672>.</span><span style=color:#66d9ef>TESTFIELD</span><span style=color:#f92672>(</span>"Document Type",VendorBillLine<span style=color:#f92672>.</span>"Document Type"::Invoice<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>((</span>VendorBillLine<span style=color:#f92672>.</span>"Vendor No." <\> PrevVendorBillLine<span style=color:#f92672>.</span>"Vendor No."<span style=color:#f92672>) </span><span style=color:#f92672>OR</span> <span style=color:#f92672>(</span>VendorBillLine<span style=color:#f92672>.</span>"Vendor Bank Acc. No." <\> PrevVendorBillLine<span style=color:#f92672>.</span>"Vendor Bank Acc. No."<span style=color:#f92672>)) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span> InsertTempGenJnlLine<span style=color:#f92672>(</span>TempGenJnlLine,VendorBillHeader,PrevVendorBillLine,CumulativeAmount<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>((</span>VendorBillLine<span style=color:#f92672>.</span>"Vendor No." <> PrevVendorBillLine<span style=color:#f92672>.</span>"Vendor No."<span style=color:#f92672>) </span><span style=color:#f92672>OR</span> <span style=color:#f92672>(</span>VendorBillLine<span style=color:#f92672>.</span>"Vendor Bank Acc. No." <> PrevVendorBillLine<span style=color:#f92672>.</span>"Vendor Bank Acc. No."<span style=color:#f92672>)) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span> InsertTempGenJnlLine<span style=color:#f92672>(</span>TempGenJnlLine,VendorBillHeader,PrevVendorBillLine,CumulativeAmount<span style=color:#f92672>)</span>;
|
||||
|
||||
CumulativeAmount <span style=color:#f92672>:=</span> VendorBillLine<span style=color:#f92672>.</span>"Amount to Pay";
|
||||
|
||||
|
|
@ -501,12 +501,12 @@ INSERT;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Hooks :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/hooks/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -312,25 +312,24 @@ ALGuidelines.Dev
|
|||
<h2 id=consequences>Consequences</h2>
|
||||
<p>This pattern can be used in all cases to put business logic. But I see three possible approaches</p>
|
||||
<ol>
|
||||
<li>You only declare the most important and most used hooks</li>
|
||||
</ol>
|
||||
<li>You only declare the most important and most used hooks
|
||||
<ul>
|
||||
<li>This way, you limit the amount of objects and hooks to only a few in the default product</li>
|
||||
<li>For example, only the OnBeforePostSalesHeader, OnBeforeReleaseSalesDocument, .. And no field validation or such…</li>
|
||||
</ul>
|
||||
<ol start=2>
|
||||
<li>Only at objects of the default application which you are customizing.</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Only at objects of the default application which you are customizing.
|
||||
<ul>
|
||||
<li>This way, you don’t want to create hooks for your own objects, only default existing objects.</li>
|
||||
</ul>
|
||||
<ol start=3>
|
||||
<li>(recommended) You create hooks on all places you don’t want to write business logic, and on all existing objects which you would like to customize.</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>(recommended) You create hooks on all places you don’t want to write business logic, and on all existing objects which you would like to customize.
|
||||
<ul>
|
||||
<li>This is a very consistent way of working, as in any case, your business logic ends up in either a hook, or in its corresponding objects from a specific design pattern. But you know that the entry point is always a hook.</li>
|
||||
<li>You know what to expect in any case, both changed business logic in existing code and business logic in newly created code is entered from a hook.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>Atomic coding: It’s important that the hook function is readable in the most extreme way. For this, we recommend to use the “Atomic Coding” concept.</p>
|
||||
<p>See here a comparison / extension of hooks : <a href=http://www.waldo.be/2016/02/29/nav-2016-hooks-or-events/>http://www.waldo.be/2016/02/29/nav-2016-hooks-or-events/</a></p>
|
||||
|
|
@ -346,12 +345,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Surrogate keys using Autoincrement Pattern :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/implementation-of-surrogate-keys-using-autoincrement-pattern/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,14 +248,14 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#usage><strong>Usage</strong></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a></li>
|
||||
<li><a href=#nav-specific-example><strong>NAV Specific Example</strong></a></li>
|
||||
<li><a href=#nav-usages><strong>NAV Usages</strong></a></li>
|
||||
<li><a href=#ideas-for-improvement><strong>Ideas for improvement</strong></a></li>
|
||||
<li><a href=#consequences-when-it-should-not-be-used><strong>Consequences (When it should not be used)</strong></a></li>
|
||||
<li><a href=#related-topics><strong>Related Topics</strong></a></li>
|
||||
<li><a href=#nav-usages>NAV Usages</a></li>
|
||||
<li><a href=#ideas-for-improvement>Ideas for improvement</a></li>
|
||||
<li><a href=#consequences-when-it-should-not-be-used>Consequences (When it should not be used)</a></li>
|
||||
<li><a href=#related-topics>Related Topics</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -266,27 +266,24 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Surrogate keys using Autoincrement Pattern</h1>
|
||||
<p><em>By <a href=http://mvp.microsoft.com/en-us/mvp/Soren%20Klemmensen-5001002 title="Soren Klemmensen">Soren Klemmensen</a>, <a href=http://partner-ready-software.com/ title=Partner-Ready-Software><em>Partner-Ready-Software</em> </a> & <a href=http://www.360visibility.com/ title="360 Visibility">360 Visibility</a></em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>This Pattern is meant to create generic & reusable links between tables. The goal is to have an easy generic way to link a generically designed sub table to a record on a main table which can be used for other links too.</p>
|
||||
<p>To minimize the impact of customizations and to keep modules as generic and reusable as possible the idea of the Implementation of surrogate keys using AutoIncrement pattern is:</p>
|
||||
<ul>
|
||||
<li>To create a generic and reusable auto generated link (A Surrogate Key), Immune to natural key data & requirement changes, on a main table with minimum impact on the table.</li>
|
||||
<li>To create generic and reusable sub tables that effortless can be reused anywhere in the application.</li>
|
||||
</ul>
|
||||
<h2 id=description><strong>Description</strong></h2>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>Over years of development many things are repeated across different implementation and even inside the same application. A typical example could be adding comments to an area just as it is done in Microsoft Dynamics NAV multiple times. There can be reasons for doing this again and again, but not only does this need to be maintained and upgraded over the years, but all the implementations of comments also needs to be tested separately. If a standard and generic comment could be developed and a generic way of connecting it to a main table this could be resolved. This is exactly what this pattern is trying accomplish.</p>
|
||||
<p><a href=0458.Figure-1.PNG><img src=0458.Figure-1.PNG alt=" "></a></p>
|
||||
<p><em>Figure 1: Table structure for linking a Document Header and Line Table with a Document Comment Table.</em></p>
|
||||
<p>__</p>
|
||||
<p>_<a href=0638.Figure-2.PNG><img src=0638.Figure-2.PNG alt=" "></a>_</p>
|
||||
<p><a href=0638.Figure-2.PNG><img src=0638.Figure-2.PNG alt=" "></a></p>
|
||||
<p><em>Figure 2: Table Structure for linking a Master Data Table with a Master Data Comment Table</em></p>
|
||||
<p>__</p>
|
||||
<p>A typical way of linking a table to master data or to a document has been to use the primary key of the table being linked to. This causes some issues as the linked table now is designed specifically for the main table and it functionality cannot be reused. In case of renames the linked table needs to be renamed too which is costly in processing. Code also needs to be added on the delete trigger of the table to ensure that the attached records get removed if needed which increases the over all footprint of any change.</p>
|
||||
<p>_<a href=0333.Figure-3.PNG><img src=0333.Figure-3.PNG alt=" "></a>_</p>
|
||||
<p><a href=0333.Figure-3.PNG><img src=0333.Figure-3.PNG alt=" "></a></p>
|
||||
<p><em>Figure 3: A Generic Way of creating a Comment table and linking it in a generic way to the main table no matter what this table might be. The Unique Record Identifier on the main tables is an Integer with AutoIncrement set to yes.</em></p>
|
||||
<p>__</p>
|
||||
<p>It is recommended using this pattern in all tables which need sub tables unless specific reasons exists for not doing this.</p>
|
||||
<h2 id=usage><strong>Usage</strong></h2>
|
||||
<h2 id=usage>Usage</h2>
|
||||
<p><strong>Step 1</strong>: Create a generic Unique Record Identifier in the main table</p>
|
||||
<p>The Pattern is implemented by adding a Field (I have called it Unique Record Identifier for this article) in a table (the main Table) where links are needed to be established to. Set the Property Data Type to Integer, Editable to No & AutoIncrement to Yes.</p>
|
||||
<p><strong>Step 2</strong>: Create a generic link-able sub table.</p>
|
||||
|
|
@ -308,27 +305,20 @@ ALGuidelines.Dev
|
|||
<h2 id=nav-specific-example><strong>NAV Specific Example</strong></h2>
|
||||
<p>Let’s assume we would like to create comment for a larger number of very different tables in the system.</p>
|
||||
<p><strong>Update the Customer table (Step 1)</strong>: Go to table 18 Customer and add Field 50000 Unique Record Identifier. Set the Property Data Type to Integer, Editable to No & AutoIncrement to Yes. Save the changes.</p>
|
||||
<p>_<a href=1488.Example-Figure-1.png><img src=1488.Example-Figure-1.png alt=" "></a>_</p>
|
||||
<p>__</p>
|
||||
<p>_<a href=4682.Example-Figure-2.png><img src=4682.Example-Figure-2.png alt=" "></a>_</p>
|
||||
<p>__</p>
|
||||
<p><a href=1488.Example-Figure-1.png><img src=1488.Example-Figure-1.png alt=" "></a></p>
|
||||
<p>_<a href=4682.Example-Figure-2.png><img src=4682.Example-Figure-2.png alt=" "></a></p>
|
||||
<p><strong>Create Comment table (Step 2)</strong>: Create a new table called Comment. Add 3 fields Table No., Unique Record Identifier & Line No. all of Data Type Integer. Make these 3 fields into the primary key for the table. Add a 4 field called Comment with Data Type Text(80). Save the changes.</p>
|
||||
<p><a href=4532.Example-Figure-3.png><img src=4532.Example-Figure-3.png alt=" "></a></p>
|
||||
<p><strong>Create the Comments page (Step 3)</strong>: Start the page wizard and create a Page based on table comment created above as a List only showing the Comment field. Set AutoSplitKey property to Yes on the page.</p>
|
||||
<p>__</p>
|
||||
<p>_<a href=2068.Example-Figure-4.png><img src=2068.Example-Figure-4.png alt=" "></a>_</p>
|
||||
<p>__</p>
|
||||
<p><strong>Update the Customer Card (Step 4)</strong>: Add an action to the Customer Card to open the Comments. Go to Actions and create an action called Smart Comment. Populate the properties RunObject, RunPageView and RunPageLink as see in the picture below.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/0552.Example-Figure-5.png><img src=0552.Example-Figure-5.png alt=" "></a></p>
|
||||
<p>__</p>
|
||||
<p><strong>Create a hook OnDatabaseDelete (Step 5)</strong>:</p>
|
||||
<p>Create a codeunit 50000 called “ApplicationManagement Hook” with one function called OnAfterOnDatabaseDelete taking the parameter RecRef of Data Type RecordRef. Add it as a global variable to Codeunit 1 ApplicationManagement and call the function as the last line in OnDatabaseDelete. Please read about the hook pattern before implementing it.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/4477.Example-Figure-6.png><img src=4477.Example-Figure-6.png alt=" "></a></p>
|
||||
<p>__</p>
|
||||
<p><strong>Create the code needed to delete comments linked to a deleted record (Step6)</strong>:</p>
|
||||
<p>Create a DeleteComments function taking the RecRef of Data Type RecordRef and add the code as shown blow.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/1884.Example-Figure-7.png><img src=1884.Example-Figure-7.png alt=" "></a></p>
|
||||
<p>__</p>
|
||||
<p>It is assumed in this example for simplicity that the Field 50000 is reserved across the entire application for the Unique Record Identifier as defined in Step 1.</p>
|
||||
<p>The comments are now fully working if we look away from the fact that we did not deal with a few things specific to Sales orders like RecreateSalesLines function, Archiving and Copy Document. All of which can easily be dealt with.</p>
|
||||
<p>These comments are now completely reusable everywhere else in the system. Sales Document is a perfect example as the primary keys of the Sales Header and the Sales line are both different from the customer and normally we would not be able to use the comments header or the line. All that needs to be done is adding the Field 50000 Unique Record Identifier to the Sales Header & Sales Line (Disregarding the posted documents in this example) and creating the actions on the Page Actions with the needed filters. Deletion is already handled of comments no matter what the main table might be.</p>
|
||||
|
|
@ -336,15 +326,14 @@ ALGuidelines.Dev
|
|||
<p>Other ideas for use of this pattern could be. An Error table, Tags, Dynamically defined fields and Generic fact boxes. Only the imagination sets limits for its use.</p>
|
||||
<p>Upgrade wise there can be an impact if data is moved out of tables to be reinserted again because of a change to a database structure. This will cause the Unique Record Identifier to change, unless steps are taken to avoid this, and the links will need to be reestablished.</p>
|
||||
<p>Other risks could be if Transfer Fields are used and data is being copied unintentionally.</p>
|
||||
<h2 id=nav-usages><strong>NAV Usages</strong></h2>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>This is a new pattern not currently used in Microsoft Dynamics NAV.</p>
|
||||
<h2 id=ideas-for-improvement><strong>Ideas for improvement</strong></h2>
|
||||
<h2 id=ideas-for-improvement>Ideas for improvement</h2>
|
||||
<p>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.</p>
|
||||
<h2 id=consequences-when-it-should-not-be-used><strong>Consequences (When it should not be used)</strong></h2>
|
||||
<h2 id=consequences-when-it-should-not-be-used>Consequences (When it should not be used)</h2>
|
||||
<p>This can be used on any table when linking anything to it that can be considered a generic module which can be reused. That said it should not be used in cases where there is a risk of tables growing so much that performance could be impacted. There are ways to reduce performance impact when using high volume tables, but that is outside the scope of this pattern.</p>
|
||||
<h2 id=related-topics><strong>Related Topics</strong></h2>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>This is related to the hook pattern as far as they both try to reduce the footprint changes have on the standard application, by creating reusable ways to interact with the standard code. That said the hook pattern is more about hooking the functionality to existing while this pattern is more about creating reusable ways of creating functionality.</p>
|
||||
<p>__</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -357,12 +346,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>1. Patterns :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -263,12 +263,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -44,8 +44,6 @@ Abstract Users or the administrator must regularly update setup or supplementary
|
|||
The navigation experience around these extra steps is often quite troublesome and time-consuming. To enable users to easily perform the needed update, a guide often gives the best support.</description></item><item><title>Error Message Processing</title><link>https://alguidelines.dev/navpatterns/1-patterns/error-message-processing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/error-message-processing/</guid><description>By Jesper Schulz at Microsoft Development Center Copenhagen
|
||||
Note: This pattern describes new functionality which makes it possible to generalize the Journal Error Processing pattern.
|
||||
Abstract Missing, invalid or incomplete data is a common issue during data processing in NAV. This article describes how to collect all error messages during processing using the error message component and present them to the user in a unified way, which enables the user to correct the errors efficiently.</description></item><item><title>Extending the Role Center Headlines</title><link>https://alguidelines.dev/navpatterns/1-patterns/extending-the-role-center-headlines/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/extending-the-role-center-headlines/</guid><description>By David Bastide at Microsoft Development Center Copenhagen
|
||||
__
|
||||
__
|
||||
Context Headlines are designed as a page of type HeadlinePart containing at least one text field. The part is added to the top of Role Center pages.
|
||||
This document provides an elegant and extensible pattern about how to extend the Role Center headlines to add your own business headlines based on your data, and display them only if relevant.
|
||||
Description The Dynamics 365 Business Central release (April 2018) introduces a new HeadlinePart page type.</description></item><item><title>Feature Localization For Data Structures</title><link>https://alguidelines.dev/navpatterns/1-patterns/feature-localization-for-data-structures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/feature-localization-for-data-structures/</guid><description>Originally by Bogdan Sturzoiu at Microsoft Development Center Copenhagen
|
||||
|
|
@ -66,13 +64,12 @@ Description This pattern creates a standard master data entity, listing all nece
|
|||
It is being used for creating a master data entity and can roughly be divided into 2 categories: Business and Product</description></item><item><title>Multi-file Download</title><link>https://alguidelines.dev/navpatterns/1-patterns/multi-file-download/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/multi-file-download/</guid><description>By Martin Dam at Microsoft Development Center Copenhagen
|
||||
Abstract The goal of this pattern is to enable the users to download multiple files as a zip file instead of downloading one by one. On the Web Client this is preferred way of delivering multiple files since it is one of the web patterns and we cannot use File Management code unit to place files silently on the machine.
|
||||
Description When generating reports that consists of multiple, and usually an unknown number of files, the developer will have to handle the download which also depends on the client the user is on.</description></item><item><title>Multi-Page List</title><link>https://alguidelines.dev/navpatterns/1-patterns/multi-page-list/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/multi-page-list/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
__
|
||||
Abstract This pattern describes how to open a related document (or card) page from a list page, for the case when there can be more than one pages associated to the rows of the list page.
|
||||
Description The example below illustrates the connection of a List Page with multiple Document Pages, while the second example links the List Page with Card Pages.</description></item><item><title>Multilanguage Application Data</title><link>https://alguidelines.dev/navpatterns/1-patterns/multilanguage-application-data/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/multilanguage-application-data/</guid><description>Originally by Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
Abstract Generally, NAV translation refers to the translation of UI elements like captions and user texts (messages on dialogs, warnings, error messages). This translation is done by the Microsoft Dynamics NAV team before releasing the localized version of the product.
|
||||
But there is one more scenario. In this scenario, Cronus International Ltd., wants to sell a &ldquo;Fiets&rdquo; to a Dutch customer, a&quot;Cykel&quot; to a Danish one, and a &ldquo;Bicicletta&rdquo; to an Italian customer.</description></item><item><title>No Series</title><link>https://alguidelines.dev/navpatterns/1-patterns/no-series/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/no-series/</guid><description>By Bogdana Botez, at Microsoft Development Center Copenhagen
|
||||
Abstract Number series assignment is widely used in Microsoft Dynamics NAV to automatically assign unique numbers to data entries.
|
||||
Description Documents and entities of any type (invoices, orders, customers, inventory items etc) are usually assigned an unique number, which can be later referenced whenever that particular entry needs to be consulted. When a new data entry is created, NAV implements the possibility to auto-assign a new number for this entry.</description></item><item><title>Observer</title><link>https://alguidelines.dev/navpatterns/1-patterns/observer/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/observer/</guid><description>By Nikolai L&rsquo;Estrange, from TVision Technology Ltd. in the UK _
|
||||
Description Documents and entities of any type (invoices, orders, customers, inventory items etc) are usually assigned an unique number, which can be later referenced whenever that particular entry needs to be consulted. When a new data entry is created, NAV implements the possibility to auto-assign a new number for this entry.</description></item><item><title>Observer</title><link>https://alguidelines.dev/navpatterns/1-patterns/observer/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/observer/</guid><description>By Nikolai L&rsquo;Estrange, from TVision Technology Ltd. in the UK
|
||||
Abstract Track all record changes against a defined table or set of tables.
|
||||
Problem Microsoft Dynamics NAV has the built in ability to track all record changes against any table, however it does not always fire the triggers for every table.
|
||||
Solution Create a setup table to define which other tables you want to track changes for, and optionally what triggers you want to fire, then link this up to the standard triggers in Codeunit 1.</description></item><item><title>Posting Routine - Select Behavior</title><link>https://alguidelines.dev/navpatterns/1-patterns/posting-routine-select-behavior/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/posting-routine-select-behavior/</guid><description>By waldo
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Instructions in the UI :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/instructions-in-the-ui/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -315,16 +315,14 @@ ALGuidelines.Dev
|
|||
<p>Important parts:<br>
|
||||
<strong>VideoPlayerAddIn.SetFrameAttribute</strong> function is used to set an attribute to the iframe that will be playing the video.</p>
|
||||
<p>Example of the embed code:</p>
|
||||
<p>You must assign <strong>src attribute</strong> to src of the embed code, for example:</p>
|
||||
<pre><code>VideoPlayer.SetFrameAttribute('src', 'https://www.youtube.com/embed/7SGp9pA9cAY');
|
||||
</code></pre>
|
||||
<p>Without this, the video will not play. You can use the same function to assign other attributes, for example to remove frame border use:</p>
|
||||
<pre><code>VideoPlayer.SetFrameAttribute(' frameborder', '0');
|
||||
</code></pre>
|
||||
<p>Height and width should be set by using the following functions, since they ensure that the video will be centered on the page.</p>
|
||||
<pre><code>VideoPlayerAddIn.SetHeight(Height) and VideoPlayerAddIn.SetWidth(Width);
|
||||
</code></pre>
|
||||
<p>If you would like to reuse the <strong>Mini Video Player Page</strong> page (1395), then use:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-js data-lang=js><span style=color:#f92672><</span><span style=color:#a6e22e>iframe</span> <span style=color:#a6e22e>width</span><span style=color:#f92672>=</span><span style=color:#e6db74>"560"</span> <span style=color:#a6e22e>height</span><span style=color:#f92672>=</span><span style=color:#e6db74>"315"</span> <span style=color:#a6e22e>src</span><span style=color:#f92672>=</span><span style=color:#e6db74>"//www.youtube.com/embed/7SGp9pA9cAY"</span> <span style=color:#a6e22e>frameborder</span><span style=color:#f92672>=</span><span style=color:#e6db74>"0"</span> <span style=color:#a6e22e>allowfullscreen</span><span style=color:#960050;background-color:#1e0010>\</span><span style=color:#f92672>><</span><span style=color:#960050;background-color:#1e0010>/iframe\></span>
|
||||
</code></pre></div><p>You must assign <strong>src attribute</strong> to src of the embed code, for example:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> VideoPlayer<span style=color:#f92672>.</span>SetFrameAttribute<span style=color:#f92672>(</span><span style=color:#e6db74>'src'</span>, <span style=color:#e6db74>'https://www.youtube.com/embed/7SGp9pA9cAY'</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Without this, the video will not play. You can use the same function to assign other attributes, for example to remove frame border use:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> VideoPlayer<span style=color:#f92672>.</span>SetFrameAttribute<span style=color:#f92672>(</span><span style=color:#e6db74>' frameborder'</span>, <span style=color:#e6db74>'0'</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Height and width should be set by using the following functions, since they ensure that the video will be centered on the page.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> VideoPlayerAddIn<span style=color:#f92672>.</span>SetHeight<span style=color:#f92672>(</span>Height<span style=color:#f92672>) </span><span style=color:#f92672>and</span> VideoPlayerAddIn<span style=color:#f92672>.</span>SetWidth<span style=color:#f92672>(</span>Width<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>If you would like to reuse the <strong>Mini Video Player Page</strong> page (1395), then use:</p>
|
||||
<pre><code>SetParameters(Height,Width,Src,Caption), which uses the functions described above.
|
||||
</code></pre>
|
||||
<p>4. As a last step you need to implement the action on the group and assign a video icon</p>
|
||||
|
|
@ -364,12 +362,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Integration of Addresses :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/integration-of-addresses/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -269,12 +269,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Journal Error Processing :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/journal-error-processing/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -287,47 +287,60 @@ ALGuidelines.Dev
|
|||
<p><a href=8640.Journal-Error-Processing-3.jpg><img src=8640.Journal-Error-Processing-3.jpg alt=" "></a></p>
|
||||
<h2 id=application-objects>Application Objects</h2>
|
||||
<p>In the following table, the Generic Object column contains the objects that you can use as a base for your implementation.</p>
|
||||
<p>Generic Object</p>
|
||||
<p>Description</p>
|
||||
<p>Sample W1 implementation of SEPA Credit Transfer*</p>
|
||||
<p>Journal Page</p>
|
||||
<p>This is the journal list page where the user invokes the processing action.</p>
|
||||
<p>Payment Journal</p>
|
||||
<p>Action on Page</p>
|
||||
<p>The processing action invoked by the user on the journal list page.</p>
|
||||
<p>Export Payments to File</p>
|
||||
<p>Errors Page List Part</p>
|
||||
<p>A FactBox that displays any journal line validation errors.</p>
|
||||
<p>To improve user experience, the developer can highlight the lines with errors in red and conveniently sort the lines with errors at the top.</p>
|
||||
<p>Payment Journal Errors Part</p>
|
||||
<p>Validation codeunit</p>
|
||||
<p>Contains code that checks that the journal line contains correct, complete, and coherent data and that the line is ready for whatever process must be done next.</p>
|
||||
<p>SEPA CT-Check Line</p>
|
||||
<p>Processing codeunit</p>
|
||||
<p>Executes the processing of the journal lines.</p>
|
||||
<p>SEPA CT-Export File</p>
|
||||
<p>Journal Error Text Table</p>
|
||||
<p>Contains</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Generic Object</th>
|
||||
<th>Description</th>
|
||||
<th>Sample W1 implementation of SEPA Credit Transfer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Journal Page</td>
|
||||
<td>This is the journal list page where the user invokes the processing action.</td>
|
||||
<td>Payment Journal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Action on Page</td>
|
||||
<td>The processing action invoked by the user on the journal list page.</td>
|
||||
<td>Export Payments to File</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Errors Page List Part</td>
|
||||
<td>A FactBox that displays any journal line validation errors.</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>To improve user experience, the developer can highlight the lines with errors in red and conveniently sort the lines with errors at the top.</td>
|
||||
<td>Payment Journal Errors Part</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Validation codeunit</td>
|
||||
<td>Contains code that checks that the journal line contains correct, complete, and coherent data and that the line is ready for whatever process must be done next.</td>
|
||||
<td>SEPA CT-Check Line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Processing codeunit</td>
|
||||
<td>Executes the processing of the journal lines.</td>
|
||||
<td>SEPA CT-Export File</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Generic Object:</strong> Journal Error Text Table</p>
|
||||
<p><strong>Description:</strong></p>
|
||||
<p>Contains:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>The error messages</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Link information about where the error messages belong. For example, in table 1228, Payment Jnl. Export Error Text, the error is linked uniquely to a journal line by the following fields:</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Journal Template Name, with TableRelation=“Gen. Journal Template”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Journal Batch Name, with TableRelation=“Gen. Journal Batch”.Name WHERE (Journal Template Name=FIELD(Journal Template Name))</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Journal Line No.</p>
|
||||
</li>
|
||||
<li>The error messages</li>
|
||||
<li>Link information about where the error messages belong. For example, in table 1228, Payment Jnl. Export Error Text, the error is linked uniquely to a journal line by the following fields:</li>
|
||||
<li>Journal Template Name, with TableRelation=“Gen. Journal Template”</li>
|
||||
<li>Journal Batch Name, with TableRelation=“Gen. Journal Batch”.Name WHERE (Journal Template Name=FIELD(Journal Template Name))</li>
|
||||
<li>Journal Line No.</li>
|
||||
</ul>
|
||||
<p>Other related information can be added, such as document number of the original source document, if the current journal line originates from a document.</p>
|
||||
<p>An extra improvement would be to add a drilldown or a link to the page where the user can fix the error. This would significantly simplify the scenario by excluding manual navigation and investigation by the user to find the page where the error can be fixed.</p>
|
||||
<p>Payment Jnl. Export Error Text</p>
|
||||
<p><strong>Sample W1 implementation of SEPA Credit Transfer:</strong> Payment Jnl. Export Error Text</p>
|
||||
<p>* The W1 implementation of file export for SEPA Credit Transfer contains the generic SEPA functionality. However, due to differences in data models and user scenarios in various country implementations, the selected local versions contain adaptations of the generic functionality.</p>
|
||||
<h2 id=flow>Flow</h2>
|
||||
<p>Find below a diagram describing the flow between the objects involved in the journal error processing.</p>
|
||||
|
|
@ -412,12 +425,12 @@ DELETEALL;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Journal Template Batch Line :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/journal-template-batch-line/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -282,7 +282,7 @@ ALGuidelines.Dev
|
|||
<h2 id=abstract>Abstract</h2>
|
||||
<p>The role of a journal line is to temporarily hold transaction data until the transaction is posted. Before posting, the entries are in a draft state, which means that they are available for corrections and/or deletion. As soon as the entries are posted, they are converted to ledger entries.</p>
|
||||
<p>Journal templates are used to specify the underlying journal structure and to provide the default information for the journal batches. Journal batches usually serve to group journal lines, such as lines created by two different users.</p>
|
||||
<p>_<a href=2438.Journal-Template-Batch-Line-1.jpg><img src=2438.Journal-Template-Batch-Line-1.jpg alt=" "></a>_</p>
|
||||
<p><a href=2438.Journal-Template-Batch-Line-1.jpg><img src=2438.Journal-Template-Batch-Line-1.jpg alt=" "></a></p>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>Journal templates and journal batches are used if there is a need to create and post one or more entries. They are implemented in multiple areas of the application, like Sales, Purchases, Cash Receipts, Payments, Fixed Assets1.</p>
|
||||
<h3 id=journal-templates>Journal Templates</h3>
|
||||
|
|
@ -295,19 +295,36 @@ ALGuidelines.Dev
|
|||
<li>No. Series</li>
|
||||
</ul>
|
||||
<p>The Journal Template table stores the relevant attributes that define the nature and behavior of the journal templates, for example:</p>
|
||||
<p>Journal Template Table Field</p>
|
||||
<p>Description</p>
|
||||
<p>Test Report ID</p>
|
||||
<p>The journals offer the possibility of running test reports3. The role of a test report is to simulate the posting process. The verification criteria for the journal lines is ran, and the report can be displayed, all without doing the actual posting. This helps finding and correcting any errors that might exist in the data.</p>
|
||||
<p>The name of the test report is the same with the name of the corresponding journal, plus the suffix " - Test". For example, the General Journal has the associated test report named General Journal - Test.</p>
|
||||
<p>Posting Report ID</p>
|
||||
<p>This report is printed when a user selects Post and Print4.</p>
|
||||
<p>Page ID</p>
|
||||
<p>For some journals, more UI objects are required. For example, the General Journals have a special page for bank and cash.</p>
|
||||
<p>Source Code</p>
|
||||
<p>Here you can enter a Trail Code for all the postings done through this Journal4.</p>
|
||||
<p>Recurring</p>
|
||||
<p>Whenever you post lines from a recurring journal, new lines are automatically created with a posting date defined in the recurring date formula.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Journal Template Table Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Test Report ID</td>
|
||||
<td>The journals offer the possibility of running test reports3. The role of a test report is to simulate the posting process. The verification criteria for the journal lines is ran, and the report can be displayed, all without doing the actual posting. This helps finding and correcting any errors that might exist in the data. The name of the test report is the same with the name of the corresponding journal, plus the suffix " - Test". For example, the General Journal has the associated test report named General Journal - Test.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Posting Report ID</td>
|
||||
<td>This report is printed when a user selects Post and Print4.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Page ID</td>
|
||||
<td>For some journals, more UI objects are required. For example, the General Journals have a special page for bank and cash.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Source Code</td>
|
||||
<td>Here you can enter a Trail Code for all the postings done through this Journal4.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recurring</td>
|
||||
<td>Whenever you post lines from a recurring journal, new lines are automatically created with a posting date defined in the recurring date formula.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Each journal template defines a default value of those attributes. The values that are defined in a template will be inherited by the journal batches, which will be created from a journal template.</p>
|
||||
<p>Microsoft Dynamics NAV is released with a number of standard journal templates predefined in the Journal Templates page. More templates can be defined by the users.</p>
|
||||
<h3 id=journal-batches>Journal Batches</h3>
|
||||
|
|
@ -317,7 +334,7 @@ ALGuidelines.Dev
|
|||
<p>Journal lines contain the actual business data (posting dates, account numbers, amounts) that will be posted as ledger entries.</p>
|
||||
<p>During posting, only the information from the journal lines is needed. However, the information has been created with the help of the journal templates and grouped together using the journal batches.</p>
|
||||
<p>Posting creates ledger entries from the temporary content that is stored in the journal lines. Ledger entries are not created directly. Instead, they are posted from journal lines.</p>
|
||||
<p>_<a href=8103.Journal-Template-Batch-Line-2.jpg><img src=8103.Journal-Template-Batch-Line-2.jpg alt=" "></a>_</p>
|
||||
<p><a href=8103.Journal-Template-Batch-Line-2.jpg><img src=8103.Journal-Template-Batch-Line-2.jpg alt=" "></a></p>
|
||||
<h3 id=aggregation>Aggregation</h3>
|
||||
<p>There is a 1:n aggregation relationship between journal templates and journal batches, as well as between journal batches and journal lines. Deleting a template will cascade deletion of the related batches and lines. Deleting a batch will cascade into deletion of related lines.</p>
|
||||
<h3 id=recurring-journals>Recurring Journals</h3>
|
||||
|
|
@ -359,28 +376,25 @@ ALGuidelines.Dev
|
|||
</ul>
|
||||
<p>The General Journals Batches page (251) is linked to the Gen. Journal Batch source table (232), which has a multiple-to-1 relationship with Gen. Journal Template table, based on the Journal Template Name field.</p>
|
||||
<p>Some of the fields in the Gen. Journal Batch table are not editable. Instead, their value is automatically calculated from the parent Gen. Journal Template table. For example, the Recurring field (22) is a FlowField with the following calculation formula:</p>
|
||||
<pre><code>Lookup("Gen. Journal Template".Recurring WHERE (Name=FIELD(Journal Template Name)))
|
||||
</code></pre>
|
||||
<p>Similarly, the Template Type field is a FlowField that gets its value from the parent table:</p>
|
||||
<pre><code>Lookup("Gen. Journal Template".Type WHERE (Name=FIELD(Journal Template Name)))
|
||||
</code></pre>
|
||||
<h3 id=setting-up-a-new-batch>Setting up a New Batch</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>Lookup</span><span style=color:#f92672>(</span>"Gen. Journal Template"<span style=color:#f92672>.</span>Recurring <span style=color:#66d9ef>WHERE</span> <span style=color:#f92672>(</span>Name=<span style=color:#66d9ef>FIELD</span><span style=color:#f92672>(</span>Journal Template Name<span style=color:#f92672>)))
|
||||
</span></code></pre></div><p>Similarly, the Template Type field is a FlowField that gets its value from the parent table:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>Lookup</span><span style=color:#f92672>(</span>"Gen. Journal Template"<span style=color:#f92672>.</span><span style=color:#66d9ef>Type</span> <span style=color:#66d9ef>WHERE</span> <span style=color:#f92672>(</span>Name=<span style=color:#66d9ef>FIELD</span><span style=color:#f92672>(</span>Journal Template Name<span style=color:#f92672>)))
|
||||
</span></code></pre></div><h3 id=setting-up-a-new-batch>Setting up a New Batch</h3>
|
||||
<p>When the user creates a new batch, the following field values are transferred from the Gen. Journal Template table to the Gen. Journal Batch table:</p>
|
||||
<pre><code>"Bal. Account Type" := GenJnlTemplate."Bal. Account Type";
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>"Bal. Account Type" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Bal. Account Type";
|
||||
|
||||
"Bal. Account No." := GenJnlTemplate."Bal. Account No.";
|
||||
"Bal. Account No." <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Bal. Account No.";
|
||||
|
||||
"No. Series" := GenJnlTemplate."No. Series";
|
||||
"No. Series" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"No. Series";
|
||||
|
||||
"Posting No. Series" := GenJnlTemplate."Posting No. Series";
|
||||
"Posting No. Series" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Posting No. Series";
|
||||
|
||||
"Reason Code" := GenJnlTemplate."Reason Code";
|
||||
"Reason Code" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Reason Code";
|
||||
|
||||
"Copy VAT Setup to Jnl. Lines" := GenJnlTemplate."Copy VAT Setup to Jnl. Lines";
|
||||
"Copy VAT Setup to Jnl. Lines" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Copy VAT Setup to Jnl. Lines";
|
||||
|
||||
"Allow VAT Difference" := GenJnlTemplate."Allow VAT Difference";
|
||||
</code></pre>
|
||||
<h3 id=cascade-record-deletion>Cascade record deletion</h3>
|
||||
"Allow VAT Difference" <span style=color:#f92672>:=</span> GenJnlTemplate<span style=color:#f92672>.</span>"Allow VAT Difference";
|
||||
</code></pre></div><h3 id=cascade-record-deletion>Cascade record deletion</h3>
|
||||
<p>When a record from the Gen. Journal Template table is deleted, the corresponding Gen. Journal Batch and Gen. Journal Line records are also deleted.</p>
|
||||
<h3 id=cascade-updates>Cascade updates</h3>
|
||||
<p>When the reason code or the posting number series change in the current batch, all linked Gen. Journal Line records are updated (see ModifyLines function on the Gen. Journal Batch table).</p>
|
||||
|
|
@ -418,12 +432,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Master Data :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/master-data/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -262,53 +262,118 @@ ALGuidelines.Dev
|
|||
<p>It is being used for creating a master data entity and can roughly be divided into 2 categories: Business and Product</p>
|
||||
<p>Examples of Master Data tables are:</p>
|
||||
<p>Business Data:</p>
|
||||
<p>Table 18: Customer</p>
|
||||
<p>Table 23: Vendor</p>
|
||||
<p>Table 270: Bank Account</p>
|
||||
<p>Table 5050: Contact</p>
|
||||
<ul>
|
||||
<li>Table 18: Customer</li>
|
||||
<li>Table 23: Vendor</li>
|
||||
<li>Table 270: Bank Account</li>
|
||||
<li>Table 5050: Contact</li>
|
||||
</ul>
|
||||
<p>Product Data:</p>
|
||||
<p>Table 15 G/L Account</p>
|
||||
<p>Table 27: Item</p>
|
||||
<p>Table 156: Resource</p>
|
||||
<p>Table 5600: Fixed Asset</p>
|
||||
<p>Table 5718: Nonstock Item</p>
|
||||
<p>Table 5913: Loaner</p>
|
||||
<ul>
|
||||
<li>Table 15 G/L Account</li>
|
||||
<li>Table 27: Item</li>
|
||||
<li>Table 156: Resource</li>
|
||||
<li>Table 5600: Fixed Asset</li>
|
||||
<li>Table 5718: Nonstock Item</li>
|
||||
<li>Table 5913: Loaner</li>
|
||||
</ul>
|
||||
<p>Master Data has attributes such as Location, Countries & Item Vendors. These tables are closely related to Master Data tables and are called Supplemental and Subsidiary tables.</p>
|
||||
<p>Supplemental:</p>
|
||||
<p>Table 9: Country/Region</p>
|
||||
<p>Table 14: Location</p>
|
||||
<ul>
|
||||
<li>Table 9: Country/Region</li>
|
||||
<li>Table 14: Location</li>
|
||||
</ul>
|
||||
<p>Subsidiary:</p>
|
||||
<p>Table 99: Item Vendor</p>
|
||||
<ul>
|
||||
<li>Table 99: Item Vendor</li>
|
||||
</ul>
|
||||
<p>Master Data is among other used in journals, posting routines and historic data like ledger entries.</p>
|
||||
<p><strong>Naming & Conventions</strong></p>
|
||||
<hr>
|
||||
<p>Table & Card Page</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Singular</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Examples: Customer, Vendor & Item</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>List Page</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Plural if Editable = TRUE.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Singular + “List” if Editable = FALSE.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h1 id=example>Example</h1>
|
||||
<p>The data entity has a single primary key field with the following properties:</p>
|
||||
<p>Field No.</p>
|
||||
<p>1</p>
|
||||
<p>Name</p>
|
||||
<p>“No.”</p>
|
||||
<p>Date Type</p>
|
||||
<p>Code 20</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Field No.</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>“No.”</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date Type</td>
|
||||
<td>Code 20</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Each master data entity has a field which gives a name tag to the data entity carrying the natural name of the entity. This field is called Name if the data entity refers to a living person or an organization, such as a customer or a vendor; it is called Description instead if the data entity does not refer to a person or organization, such as an item. The field has the following properties:</p>
|
||||
<p>Name</p>
|
||||
<p>Name or Description</p>
|
||||
<p>Date Type</p>
|
||||
<p>Text 50</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Name or Description</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date Type</td>
|
||||
<td>Text 50</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>An added benefit of using the Name or Description field naming is that this will be part of the dropdown when looking up based on the table relation.</p>
|
||||
<p>The table properties of a master data table contain the following entries:</p>
|
||||
<p>LookupPageID</p>
|
||||
<p>A ListType Page referring to the table which is not editable.</p>
|
||||
<p>DrillDownPageID</p>
|
||||
<p>The same page as defined in the LookupPageID</p>
|
||||
<p>DataCaptionFields</p>
|
||||
<p>The primary key plus the field which provides the primary name tag for the record. This will typically be the Name or Description field defined earlier.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>LookupPageID</td>
|
||||
<td>A ListType Page referring to the table which is not editable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DrillDownPageID</td>
|
||||
<td>The same page as defined in the LookupPageID</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataCaptionFields</td>
|
||||
<td>The primary key plus the field which provides the primary name tag for the record. This will typically be the Name or Description field defined earlier.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h1 id=nav-specific-example>NAV Specific Example</h1>
|
||||
<p>We will create an Example table here with a Card and List Page as described above.</p>
|
||||
<p>First we create the Table with No. as the primary key.</p>
|
||||
|
|
@ -327,17 +392,21 @@ ALGuidelines.Dev
|
|||
<h1 id=nav-usages>NAV Usages</h1>
|
||||
<p>You can see this pattern used in the following tables & pages:</p>
|
||||
<p>Business Data:</p>
|
||||
<p>Table 18: Customer, Page 21 Customer Card & Page 22 Customer List</p>
|
||||
<p>Table 23: Vendor, Page 26 Vendor Card & Page 27 Vendor List</p>
|
||||
<p>Table 270: Bank Account, Page 370 Bank Account Card & Page 371 Bank Account List</p>
|
||||
<p>Table 5050: Contact, Page 5050 Contact Card & Page 5052 Contact List</p>
|
||||
<ul>
|
||||
<li>Table 18: Customer, Page 21 Customer Card & Page 22 Customer List</li>
|
||||
<li>Table 23: Vendor, Page 26 Vendor Card & Page 27 Vendor List</li>
|
||||
<li>Table 270: Bank Account, Page 370 Bank Account Card & Page 371 Bank Account List</li>
|
||||
<li>Table 5050: Contact, Page 5050 Contact Card & Page 5052 Contact List</li>
|
||||
</ul>
|
||||
<p>Product Data:</p>
|
||||
<p>Table 15 G/L Account, Page 17 G/L Account Card & Page 18 G/L Account List</p>
|
||||
<p>Table 27: Item, Page 30 Item Card & Page 31 Item List</p>
|
||||
<p>Table 156: Resource, Page 76 Resource Card & Page 77 Resource List</p>
|
||||
<p>Table 5600: Fixed Asset, Page 5600 Fixed Asset Card & Page 5601 Fixed Asset List</p>
|
||||
<p>Table 5718: Nonstock Item, Page 5725 Nonstock Item Card & Page 5726 Nonstock Item List</p>
|
||||
<p>Table 5913: Loaner, Page 5922 Loaner Card & Page 5923 Loaner List</p>
|
||||
<ul>
|
||||
<li>Table 15 G/L Account, Page 17 G/L Account Card & Page 18 G/L Account List</li>
|
||||
<li>Table 27: Item, Page 30 Item Card & Page 31 Item List</li>
|
||||
<li>Table 156: Resource, Page 76 Resource Card & Page 77 Resource List</li>
|
||||
<li>Table 5600: Fixed Asset, Page 5600 Fixed Asset Card & Page 5601 Fixed Asset List</li>
|
||||
<li>Table 5718: Nonstock Item, Page 5725 Nonstock Item Card & Page 5726 Nonstock Item List</li>
|
||||
<li>Table 5913: Loaner, Page 5922 Loaner Card & Page 5923 Loaner List</li>
|
||||
</ul>
|
||||
<h1 id=consequences>Consequences</h1>
|
||||
<p>This pattern should not be used when this is not Master Data.</p>
|
||||
<h1 id=references>References</h1>
|
||||
|
|
@ -354,12 +423,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Multi-file Download :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/multi-file-download/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -280,39 +280,37 @@ ALGuidelines.Dev
|
|||
<p>For first step consists of a loop that goes through the files that needs to be downloaded. If it is on the Web client, the files are added to a ZIP archive server-side using a naming convention defined by the integration function GetSeriesFileName. This function takes a filename and number, and transforms it to unique names following a meaningful deterministic pattern e.g. prepend an integer before the file extension. The same function is used when the temporary files are created server side, so the files can be found deterministically later. This removes the need for storing filenames and consequently allows an arbitrary number of files. The second integration function: GetTotalNumberOfFiles, returns the total number of files generated during the data processing and makes the pattern able to handle an arbitrary number of files.</p>
|
||||
<p>The second step is the actually download of file(s). For the Web client this consists of closing the ZIP achieve and downloading via the standard download handler that works in the Web client. For the Win client, the files are saved directly to the client during the first step.</p>
|
||||
<p>Code 1: File loop shows an example implementation of this pattern. ServerFileName is generated at the beginning of the report/codeunit, and is the base for GetSeriesFilename. The file that is actually written to during data processing is stored in another variable which holds the output from GetSeriesFilename on the current file number. Note; the example code will only create a ZIP file if there in fact are multiple files to be downloaded.</p>
|
||||
<pre><code>IF FileName = '' THEN
|
||||
ERROR(SupplyFileNameErr);
|
||||
IF ZipMultipleFiles AND (GetTotalNumberOfFiles \> 1) AND FileManagement.IsWebClient
|
||||
THEN BEGIN
|
||||
Basename := FileManagement.GetFileName(FileName);
|
||||
ZipFileName := FileManagement.CreateZipArchiveObject;
|
||||
FOR FileNo := 1 TO GetTotalNumberOfFiles DO
|
||||
FileManagement.AddFileToZipArchive(
|
||||
GetSeriesFilename(ServerFileName,FileNo),GetSeriesFilename(Basename,FileNo));
|
||||
FileManagement.DownloadHandler(ZipFileName,'','','',
|
||||
STRSUBSTNO('%1.zip',FileManagement.GetFileNameWithoutExtension(FileName)))
|
||||
END ELSE BEGIN
|
||||
IF FileManagement.IsWebClient THEN BEGIN
|
||||
IF GetTotalNumberOfFile \> 1 THEN
|
||||
ERROR(MultipleFilesWebClientErr);
|
||||
FileManagementDownloadHandler(GetSeriesFilename(ServerFileName,1),'','','',
|
||||
FileManagement.GetFileName(FileName));
|
||||
END ELSE
|
||||
FOR FileNo := 1 TO GetTotalNumberOfFiles DO
|
||||
FileManagement.DownloadToFile(GetSeriesFilieName(ServerFileName,FileNo),
|
||||
GetSeriesFilename(FileName,FileNo));
|
||||
END;
|
||||
</code></pre>
|
||||
<p><em>Code 1: File loop</em></p>
|
||||
<p>__</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> FileName = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>SupplyFileNameErr<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> ZipMultipleFiles <span style=color:#f92672>AND</span> <span style=color:#f92672>(</span>GetTotalNumberOfFiles \> <span style=color:#ae81ff>1</span><span style=color:#f92672>) </span><span style=color:#f92672>AND</span> FileManagement<span style=color:#f92672>.</span>IsWebClient
|
||||
<span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
Basename <span style=color:#f92672>:=</span> FileManagement<span style=color:#f92672>.</span>GetFileName<span style=color:#f92672>(</span>FileName<span style=color:#f92672>)</span>;
|
||||
ZipFileName <span style=color:#f92672>:=</span> FileManagement<span style=color:#f92672>.</span>CreateZipArchiveObject;
|
||||
<span style=color:#66d9ef>FOR</span> FileNo <span style=color:#f92672>:=</span> <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>TO</span> GetTotalNumberOfFiles <span style=color:#66d9ef>DO</span>
|
||||
FileManagement<span style=color:#f92672>.</span>AddFileToZipArchive<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span>GetSeriesFilename<span style=color:#f92672>(</span>ServerFileName,FileNo<span style=color:#f92672>)</span>,GetSeriesFilename<span style=color:#f92672>(</span>Basename,FileNo<span style=color:#f92672>))</span>;
|
||||
FileManagement<span style=color:#f92672>.</span>DownloadHandler<span style=color:#f92672>(</span>ZipFileName,<span style=color:#e6db74>''</span>,<span style=color:#e6db74>''</span>,<span style=color:#e6db74>''</span>,
|
||||
STRSUBSTNO<span style=color:#f92672>(</span><span style=color:#e6db74>'%1.zip'</span>,FileManagement<span style=color:#f92672>.</span>GetFileNameWithoutExtension<span style=color:#f92672>(</span>FileName<span style=color:#f92672>)))
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>END</span> <span style=color:#66d9ef>ELSE</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> FileManagement<span style=color:#f92672>.</span>IsWebClient <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> GetTotalNumberOfFile > <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>MultipleFilesWebClientErr<span style=color:#f92672>)</span>;
|
||||
FileManagementDownloadHandler<span style=color:#f92672>(</span>GetSeriesFilename<span style=color:#f92672>(</span>ServerFileName,<span style=color:#ae81ff>1</span><span style=color:#f92672>)</span>,<span style=color:#e6db74>''</span>,<span style=color:#e6db74>''</span>,<span style=color:#e6db74>''</span>,
|
||||
FileManagement<span style=color:#f92672>.</span>GetFileName<span style=color:#f92672>(</span>FileName<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span> <span style=color:#66d9ef>ELSE</span>
|
||||
<span style=color:#66d9ef>FOR</span> FileNo <span style=color:#f92672>:=</span> <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>TO</span> GetTotalNumberOfFiles <span style=color:#66d9ef>DO</span>
|
||||
FileManagement<span style=color:#f92672>.</span>DownloadToFile<span style=color:#f92672>(</span>GetSeriesFilieName<span style=color:#f92672>(</span>ServerFileName,FileNo<span style=color:#f92672>)</span>,
|
||||
GetSeriesFilename<span style=color:#f92672>(</span>FileName,FileNo<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><em>Code 1: File loop</em></p>
|
||||
<p>The following code is an example implementation of the GetSeriesFilename function. It needs to support the case where no directory is given, only a filename, in order to add files to the root of the ZIP archive. The example will add a file number right before the extension, e.g. C:\directory\file.txt will become C:\directory\file1.txt etc.</p>
|
||||
<pre><code>LOCAL GetSeriesFilename(FileName : Text;FileNo : Integer) : Text
|
||||
IF STRPOS(FileName,'\\') <\> 0 THEN
|
||||
Directory := FileMgt.GetDirectoryName(FileName) + '\\';
|
||||
EXIT(Directory + FileMgt.GetFileNameWithoutExtension(FileName) + FORMAT(FileNo) + '.' +
|
||||
FileMgt.GetExtension(FileName));
|
||||
</code></pre>
|
||||
<h4 id=_code-2-getseriesfilename_><em>Code 2: GetSeriesFilename</em></h4>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> GetSeriesFilename<span style=color:#f92672>(</span>FileName : <span style=color:#66d9ef>Text</span>;FileNo : <span style=color:#66d9ef>Integer</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Text</span>
|
||||
<span style=color:#66d9ef>IF</span> STRPOS<span style=color:#f92672>(</span>FileName,<span style=color:#e6db74>'\\'</span><span style=color:#f92672>) </span><> <span style=color:#ae81ff>0</span> <span style=color:#66d9ef>THEN</span>
|
||||
Directory <span style=color:#f92672>:=</span> FileMgt<span style=color:#f92672>.</span>GetDirectoryName<span style=color:#f92672>(</span>FileName<span style=color:#f92672>) </span>+ <span style=color:#e6db74>'\\'</span>;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>Directory + FileMgt<span style=color:#f92672>.</span>GetFileNameWithoutExtension<span style=color:#f92672>(</span>FileName<span style=color:#f92672>) </span>+ FORMAT<span style=color:#f92672>(</span>FileNo<span style=color:#f92672>) </span>+ <span style=color:#e6db74>'.'</span> +
|
||||
FileMgt<span style=color:#f92672>.</span>GetExtension<span style=color:#f92672>(</span>FileName<span style=color:#f92672>))</span>;
|
||||
</code></pre></div><h4 id=_code-2-getseriesfilename_><em>Code 2: GetSeriesFilename</em></h4>
|
||||
<p>The pattern depends on .NET library System.IO.Compression.ZipFile, which from NAV 2015 is implemented in Codeunit 419 (File management). It consists of three functions:</p>
|
||||
<ul>
|
||||
<li>CreateZipArchiveObject: Which creates a System.IO.Compression.ZipArchive on a server side file</li>
|
||||
|
|
@ -340,12 +338,12 @@ FileMgt.GetExtension(FileName));
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Multi-Page List :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/multi-page-list/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -250,11 +250,11 @@ ALGuidelines.Dev
|
|||
<ul>
|
||||
<li>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#usage><strong>Usage</strong></a></li>
|
||||
<li><a href=#nav-specific-example><strong>NAV Specific Example</strong></a></li>
|
||||
<li><a href=#nav-usages--anchor3><strong>NAV Usages</strong><a href=http://sharepointemea/sites/DynamicsNAV/Wiki/Nav%20Wiki%20Documents/NAV%20App%20Patterns/NAV%20App%20Patterns%20for%20Review/Multi-Page%20List.docx#_msocom_7> </a></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a></li>
|
||||
<li><a href=#nav-specific-example>NAV Specific Example</a></li>
|
||||
<li><a href=#nav-usages>NAV Usages</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -267,10 +267,9 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Multi-Page List</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>__</p>
|
||||
<h3 id=abstract><strong>Abstract</strong></h3>
|
||||
<h3 id=abstract>Abstract</h3>
|
||||
<p>This pattern describes how to open a related document (or card) page from a list page, for the case when there can be more than one pages associated to the rows of the list page.</p>
|
||||
<h3 id=description><strong>Description</strong></h3>
|
||||
<h3 id=description>Description</h3>
|
||||
<p>The example below illustrates the connection of a List Page with multiple Document Pages, while the second example links the List Page with Card Pages.</p>
|
||||
<p><a href=Multi-page-list-img-1.jpg><img src=Multi-page-list-img-1.jpg alt=" "></a></p>
|
||||
<p>The records contained in a list page have an associated page, which is specified in the CardPageID property of the list page. The NAV infrastructure assures the following scenarios are in place, without the need to add any explicit C/AL code:</p>
|
||||
|
|
@ -279,61 +278,66 @@ ALGuidelines.Dev
|
|||
<li>The “Edit” action is available on the ribbon as well as in the right-click context menu of the list page rows. Invoking this action, opens the related card page.</li>
|
||||
</ol>
|
||||
<p>However, there are situations when rows of the list page can correspond to different pages each (either cards or documents). For example, consider a list page containing 3 rows, requiring the following behaviour:</p>
|
||||
<p>Row1</p>
|
||||
<p>Opens page ID 1</p>
|
||||
<p>Row2</p>
|
||||
<p>Opens page ID 2</p>
|
||||
<p>Row3</p>
|
||||
<p>Opens page ID 3</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Row1</td>
|
||||
<td>Opens page ID 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Row2</td>
|
||||
<td>Opens page ID 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Row3</td>
|
||||
<td>Opens page ID 3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>This situation is not handled automatically by NAV. There is no possibility to specify more than one CardPageID in the list page properties. Furthermore, there is no possibility to specify one or more document page IDs on the list page. Therefore, those cases need to be handled explicitly by the C/AL developer.</p>
|
||||
<h3 id=usage><strong>Usage</strong></h3>
|
||||
<h3 id=usage>Usage</h3>
|
||||
<p>The solution used in NAV implementations is at the list page level, as following:</p>
|
||||
<ol>
|
||||
<li>The property CardPageID of the list page remains undefined.</li>
|
||||
<li>An action named “Show Document” or “Card” is created on the Navigate tab, with the properties:</li>
|
||||
</ol>
|
||||
<li>
|
||||
<p>The property CardPageID of the list page remains undefined.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>An action named “Show Document” or “Card” is created on the Navigate tab, with the properties:</p>
|
||||
<ul>
|
||||
<li>Image = EditLines</li>
|
||||
<li>Promoted = Yes</li>
|
||||
<li>ShortCutKey = Shift+F7</li>
|
||||
</ul>
|
||||
<ol>
|
||||
<li>The OnAction trigger for the Card action, contains explicit logic to run the targeted card page. It can, for example, be a CASE statement, which invokes PAGE.RUN(…) based on an enumeration field of the current row.</li>
|
||||
</li>
|
||||
<li>
|
||||
<p>The OnAction trigger for the Card action, contains explicit logic to run the targeted card page. It can, for example, be a CASE statement, which invokes PAGE.RUN(…) based on an enumeration field of the current row.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h3 id=nav-specific-example><strong>NAV Specific Example</strong></h3>
|
||||
<h3 id=nav-specific-example>NAV Specific Example</h3>
|
||||
<p>For example, the NAV page Sales List (page ID 45), which displays the Sales Header Table (table ID 36), chooses which card to open, based on the Document Type field. This is an option field, which can have the following values: Quote, Order, Invoice, Credit Memo, Blanket Order, Return Order. For each document type, the related card page must be opened.</p>
|
||||
<p><a href=Multi-page-list-img-2.jpg><img src=Multi-page-list-img-2.jpg alt=" "></a></p>
|
||||
<p>For this purpose, a new action (“Card”) is added to the Sales List page. The OnAction trigger of this new action contains the page selection logic:</p>
|
||||
<pre><code>CASE "Document Type" OF
|
||||
|
||||
"Document Type"::Quote:
|
||||
|
||||
PAGE.RUN(PAGE::"Sales Quote",Rec);
|
||||
|
||||
"Document Type"::Order:
|
||||
|
||||
PAGE.RUN(PAGE::"Sales Order",Rec);
|
||||
|
||||
"Document Type"::Invoice:
|
||||
|
||||
PAGE.RUN(PAGE::"Sales Invoice",Rec);
|
||||
|
||||
"Document Type"::"Return Order":
|
||||
|
||||
PAGE.RUN(PAGE::"Sales Return Order",Rec);
|
||||
|
||||
"Document Type"::"Credit Memo":
|
||||
|
||||
PAGE.RUN(PAGE::"Sales Credit Memo",Rec);
|
||||
|
||||
"Document Type"::"Blanket Order":[
|
||||
][anchor2]
|
||||
|
||||
PAGE.RUN(PAGE::"Blanket Sales Order",Rec);
|
||||
|
||||
END;
|
||||
</code></pre>
|
||||
<h3 id=nav-usages--anchor3><strong>NAV Usages</strong><a href=http://sharepointemea/sites/DynamicsNAV/Wiki/Nav%20Wiki%20Documents/NAV%20App%20Patterns/NAV%20App%20Patterns%20for%20Review/Multi-Page%20List.docx#_msocom_7> </a></h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>CASE</span> "Document Type" <span style=color:#66d9ef>OF</span>
|
||||
"Document Type"::Quote:
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Sales Quote",Rec<span style=color:#f92672>)</span>;
|
||||
"Document Type"::<span style=color:#66d9ef>Order</span>:
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Sales Order",Rec<span style=color:#f92672>)</span>;
|
||||
"Document Type"::Invoice:
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Sales Invoice",Rec<span style=color:#f92672>)</span>;
|
||||
"Document Type"::"Return Order":
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Sales Return Order",Rec<span style=color:#f92672>)</span>;
|
||||
"Document Type"::"Credit Memo":
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Sales Credit Memo",Rec<span style=color:#f92672>)</span>;
|
||||
"Document Type"::"Blanket Order":
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Blanket Sales Order",Rec<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><h3 id=nav-usages>NAV Usages</h3>
|
||||
<p>Some of the NAV implementations of this pattern can be found in the following pages:</p>
|
||||
<ol>
|
||||
<li>Sales List (45) and Sales List Archive (5159)</li>
|
||||
|
|
@ -354,12 +358,12 @@ END;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Multilanguage Application Data :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/multilanguage-application-data/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -288,15 +288,29 @@ ALGuidelines.Dev
|
|||
<h2 id=usage>Usage</h2>
|
||||
<p><strong>Create the translation table</strong></p>
|
||||
<p>Named “<Entity> Translation” table, where <Entity> is replaced with the name of the actual object being translated. For the Item example above, this table will be named “Item Translation”.</p>
|
||||
<p>The table definition contains at a minimum:
|
||||
<strong>Field</strong>
|
||||
<strong>Description</strong>
|
||||
Entity ID field
|
||||
For example, Item No.
|
||||
Language Code
|
||||
Identifies the language of this translation string (for example, “DAN” (Danish), “BGR”(Bulgarian). This is one of the language codes defined in the Languages table.
|
||||
Translation
|
||||
The translated string.</p>
|
||||
<p>The table definition contains at a minimum:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Entity ID field</td>
|
||||
<td>For example, Item No.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Language Code</td>
|
||||
<td>Identifies the language of this translation string (for example, “DAN” (Danish), “BGR”(Bulgarian). This is one of the language codes defined in the Languages table.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Translation</td>
|
||||
<td>The translated string.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The table above has a key composed of the first two fields.</p>
|
||||
<p><strong>Create the user interface for entering new translations of <Entity></strong></p>
|
||||
<ul>
|
||||
|
|
@ -312,18 +326,33 @@ The translated string.</p>
|
|||
<li>Unit of Measure Translation</li>
|
||||
</ol>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>The <strong>Extended Text</strong> pattern is a more powerful version of the <strong>Multilanguage application data</strong> pattern presented in this section. The main differences are: <strong>Pattern</strong>
|
||||
<strong>Multilanguage Application Data</strong>
|
||||
<strong>Extended Text</strong>
|
||||
<strong>Supports translation of application data</strong>
|
||||
Yes
|
||||
Yes
|
||||
<strong>Format</strong>
|
||||
Single- or multi-line
|
||||
Single-line
|
||||
<strong>Applies to document type</strong>
|
||||
Can choose which document types are affected.
|
||||
All document types are affected.</p>
|
||||
<p>The <strong>Extended Text</strong> pattern is a more powerful version of the <strong>Multilanguage application data</strong> pattern presented in this section. The main differences are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Pattern</th>
|
||||
<th>Multilanguage Application Data</th>
|
||||
<th>Extended Text</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Supports translation of application data</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Format</td>
|
||||
<td>Single- or multi-line</td>
|
||||
<td>Single-line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Applies to document type</td>
|
||||
<td>Can choose which document types are affected.</td>
|
||||
<td>All document types are affected.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -336,12 +365,12 @@ All document types are affected.</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/net-exception-handling-in-cal/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>NET Exception Handling in CAL :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/net-exception-handling-in-cal/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -302,111 +302,131 @@ ALGuidelines.Dev
|
|||
<p>For instance, if a failure to establish a connection to the web service due to lack of Internet access, a <strong>WebException</strong> is thrown with the relevant error details. <strong>COD1290 Web Service Mgt.</strong> codeunit wraps up the required functionality to interact with a web service in C/AL, handling all the required plumping work to send web requests, receive web responses, and extract valid and error details from the web response.</p>
|
||||
<h3 id=code-sample>Code Sample</h3>
|
||||
<p>The “External Data Handling Codeunit” is a consumer of <strong>COD1290 Web Service Mgt.</strong> codeunit. If a runtime exception occurs, it gets handled as follows:</p>
|
||||
<pre><code>LOCAL PROCEDURE SendDataToConversionService@1(VAR PaymentFileTempBlob@1003 : Record 99008535;BodyTempBlob@1004 : Record 99008535;PostingExch@1007 : Record 1220);
|
||||
VAR
|
||||
BankDataConvServiceSetup@1000 : Record 1260;
|
||||
WebServiceRequestMgt@1001 : Codeunit 1290;
|
||||
BodyInStream@1005 : InStream;
|
||||
ResponseInStream@1002 : InStream;
|
||||
BEGIN
|
||||
IF NOT BodyTempBlob.Blob.HASVALUE THEN
|
||||
ERROR(NoRequestBodyErr);
|
||||
PrepareSOAPRequestBody(BodyTempBlob);
|
||||
COMMIT;
|
||||
BankDataConvServiceSetup.GET;
|
||||
BodyTempBlob.Blob.CREATEINSTREAM(BodyInStream);
|
||||
WebServiceRequestMgt.SetGlobals(BodyInStream,
|
||||
BankDataConvServiceSetup."Service URL",BankDataConvServiceSetup."User Name",BankDataConvServiceSetup.GetPassword);
|
||||
IF NOT WebServiceRequestMgt.RUN THEN
|
||||
WebServiceRequestMgt.ProcessFaultResponse;
|
||||
WebServiceRequestMgt.GetResponseContent(ResponseInStream);
|
||||
CheckIfErrorsOccurred(ResponseInStream,PostingExch);
|
||||
ReadContentFromResponse(PaymentFileTempBlob,ResponseInStream);
|
||||
END;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> SendDataToConversionService@<span style=color:#ae81ff>1</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> PaymentFileTempBlob@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>99008535</span>;BodyTempBlob@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>99008535</span>;PostingExch@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1220</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankDataConvServiceSetup@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1260</span>;
|
||||
WebServiceRequestMgt@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1290</span>;
|
||||
BodyInStream@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
ResponseInStream@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> BodyTempBlob<span style=color:#f92672>.</span><span style=color:#66d9ef>Blob</span><span style=color:#f92672>.</span>HASVALUE <span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>NoRequestBodyErr<span style=color:#f92672>)</span>;
|
||||
|
||||
PROCEDURE ProcessFaultResponse@15();
|
||||
VAR
|
||||
XMLDOMMgt@1006 : Codeunit 6224;
|
||||
DotNetExceptionHandler@1000 : Codeunit 1291;
|
||||
WebException@1005 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebException";
|
||||
WebExceptionStatus@1004 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebExceptionStatus";
|
||||
XmlDoc@1003 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument";
|
||||
HttpWebResponseError@1007 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebResponse";
|
||||
HttpStatusCode@1008 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseInputStream@1002 : InStream;
|
||||
BEGIN
|
||||
DotNetExceptionHandler.Collect;
|
||||
IF NOT DotNetExceptionHandler.CastToType(WebException,GETDOTNETTYPE(WebException)) THEN
|
||||
DotNetExceptionHandler.Rethrow;
|
||||
IF NOT WebException.Status.Equals(WebExceptionStatus.ProtocolError) THEN
|
||||
ERROR(WebException.Message);
|
||||
ResponseInputStream := WebException.Response.GetResponseStream;
|
||||
DebugLogStreamToTempFile(ResponseInputStream,'WebExceptionResponse',TempDebugLogTempBlob);
|
||||
HttpWebResponseError := WebException.Response;
|
||||
IF NOT (HttpWebResponseError.StatusCode.Equals(HttpStatusCode.Found) OR
|
||||
HttpWebResponseError.StatusCode.Equals(HttpStatusCode.InternalServerError))
|
||||
THEN
|
||||
ERROR(WebException.Message);
|
||||
XmlDoc := XmlDoc.XmlDocument;
|
||||
XmlDoc.Load(ResponseInputStream);
|
||||
ERROR(XMLDOMMgt.FindNodeTextWithNamespace(XmlDoc.DocumentElement,FaultStringXmlPathTxt,'soap',SoapNamespaceTxt));
|
||||
END;
|
||||
PrepareSOAPRequestBody<span style=color:#f92672>(</span>BodyTempBlob<span style=color:#f92672>)</span>;
|
||||
|
||||
OBJECT Codeunit 1291 DotNet Exception Handler
|
||||
COMMIT;
|
||||
|
||||
BankDataConvServiceSetup<span style=color:#f92672>.</span>GET;
|
||||
BodyTempBlob<span style=color:#f92672>.</span><span style=color:#66d9ef>Blob</span><span style=color:#f92672>.</span>CREATEINSTREAM<span style=color:#f92672>(</span>BodyInStream<span style=color:#f92672>)</span>;
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>SetGlobals<span style=color:#f92672>(</span>BodyInStream,
|
||||
BankDataConvServiceSetup<span style=color:#f92672>.</span>"Service URL",BankDataConvServiceSetup<span style=color:#f92672>.</span>"User Name",BankDataConvServiceSetup<span style=color:#f92672>.</span>GetPassword<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> WebServiceRequestMgt<span style=color:#f92672>.</span>RUN <span style=color:#66d9ef>THEN</span>
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>ProcessFaultResponse;
|
||||
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>GetResponseContent<span style=color:#f92672>(</span>ResponseInStream<span style=color:#f92672>)</span>;
|
||||
|
||||
CheckIfErrorsOccurred<span style=color:#f92672>(</span>ResponseInStream,PostingExch<span style=color:#f92672>)</span>;
|
||||
|
||||
ReadContentFromResponse<span style=color:#f92672>(</span>PaymentFileTempBlob,ResponseInStream<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> ProcessFaultResponse@<span style=color:#ae81ff>15</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
XMLDOMMgt@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>6224</span>;
|
||||
DotNetExceptionHandler@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1291</span>;
|
||||
WebException@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebException";
|
||||
WebExceptionStatus@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebExceptionStatus";
|
||||
XmlDoc@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>DotNet</span> "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument";
|
||||
HttpWebResponseError@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebResponse";
|
||||
HttpStatusCode@<span style=color:#ae81ff>1008</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseInputStream@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
DotNetExceptionHandler<span style=color:#f92672>.</span>Collect;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> DotNetExceptionHandler<span style=color:#f92672>.</span>CastToType<span style=color:#f92672>(</span>WebException,GETDOTNETTYPE<span style=color:#f92672>(</span>WebException<span style=color:#f92672>)) </span><span style=color:#66d9ef>THEN</span>
|
||||
DotNetExceptionHandler<span style=color:#f92672>.</span>Rethrow;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> WebException<span style=color:#f92672>.</span>Status<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>WebExceptionStatus<span style=color:#f92672>.</span>ProtocolError<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>WebException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
ResponseInputStream <span style=color:#f92672>:=</span> WebException<span style=color:#f92672>.</span>Response<span style=color:#f92672>.</span>GetResponseStream;
|
||||
DebugLogStreamToTempFile<span style=color:#f92672>(</span>ResponseInputStream,<span style=color:#e6db74>'WebExceptionResponse'</span>,TempDebugLogTempBlob<span style=color:#f92672>)</span>;
|
||||
|
||||
HttpWebResponseError <span style=color:#f92672>:=</span> WebException<span style=color:#f92672>.</span>Response;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> <span style=color:#f92672>(</span>HttpWebResponseError<span style=color:#f92672>.</span>StatusCode<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>HttpStatusCode<span style=color:#f92672>.</span>Found<span style=color:#f92672>) </span><span style=color:#f92672>OR</span>
|
||||
HttpWebResponseError<span style=color:#f92672>.</span>StatusCode<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>HttpStatusCode<span style=color:#f92672>.</span>InternalServerError<span style=color:#f92672>))
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>WebException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
XmlDoc <span style=color:#f92672>:=</span> XmlDoc<span style=color:#f92672>.</span><span style=color:#66d9ef>XmlDocument</span>;
|
||||
XmlDoc<span style=color:#f92672>.</span>Load<span style=color:#f92672>(</span>ResponseInputStream<span style=color:#f92672>)</span>;
|
||||
|
||||
ERROR<span style=color:#f92672>(</span>XMLDOMMgt<span style=color:#f92672>.</span>FindNodeTextWithNamespace<span style=color:#f92672>(</span>XmlDoc<span style=color:#f92672>.</span>DocumentElement,FaultStringXmlPathTxt,<span style=color:#e6db74>'soap'</span>,SoapNamespaceTxt<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OBJECT <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1291</span> <span style=color:#66d9ef>DotNet</span> Exception Handler
|
||||
{
|
||||
OBJECT-PROPERTIES
|
||||
{
|
||||
Date=;
|
||||
Time=;
|
||||
Version List=;
|
||||
OBJECT<span style=color:#f92672>-</span>PROPERTIES
|
||||
{
|
||||
<span style=color:#66d9ef>Date</span>=;
|
||||
<span style=color:#66d9ef>Time</span>=;
|
||||
<span style=color:#66d9ef>Version</span> <span style=color:#66d9ef>List</span>=;
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
OnRun=<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
}
|
||||
<span style=color:#66d9ef>CODE</span>
|
||||
{
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
OuterException@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Exception";
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Catch@<span style=color:#ae81ff>3</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Exception@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";<span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
Collect;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> CastToType<span style=color:#f92672>(</span>Exception,<span style=color:#66d9ef>Type</span><span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
Rethrow;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Collect@<span style=color:#ae81ff>1</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
OuterException <span style=color:#f92672>:=</span> GETLASTERROROBJECT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> TryCastToType@<span style=color:#ae81ff>5</span><span style=color:#f92672>(</span><span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
Exception@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>CastToType<span style=color:#f92672>(</span>Exception,<span style=color:#66d9ef>Type</span><span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> CastToType@<span style=color:#ae81ff>2</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Exception@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";<span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
Exception <span style=color:#f92672>:=</span> OuterException;
|
||||
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#66d9ef>Type</span><span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>Exception<span style=color:#f92672>.</span>GetType<span style=color:#f92672>()) </span><span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
Exception <span style=color:#f92672>:=</span> Exception<span style=color:#f92672>.</span>InnerException;
|
||||
<span style=color:#66d9ef>UNTIL</span> ISNULL<span style=color:#f92672>(</span>Exception<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Rethrow@<span style=color:#ae81ff>4</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> ISNULL<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>InnerException<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>InnerException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
ERROR<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>END</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672> </span>}
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
OnRun=BEGIN
|
||||
END;
|
||||
}
|
||||
CODE
|
||||
{
|
||||
VAR
|
||||
OuterException@1000 : DotNet "'mscorlib'.System.Exception";
|
||||
PROCEDURE Catch@3(VAR Exception@1002 : DotNet "'mscorlib'.System.FormatException";Type@1007 : DotNet "'mscorlib'.System.Type");
|
||||
BEGIN
|
||||
Collect;
|
||||
IF NOT CastToType(Exception,Type) THEN
|
||||
Rethrow;
|
||||
END;
|
||||
PROCEDURE Collect@1();
|
||||
BEGIN
|
||||
OuterException := GETLASTERROROBJECT;
|
||||
END;
|
||||
PROCEDURE TryCastToType@5(Type@1000 : DotNet "'mscorlib'.System.Type") : Boolean;
|
||||
VAR
|
||||
Exception@1001 : DotNet "'mscorlib'.System.FormatException";
|
||||
BEGIN
|
||||
EXIT(CastToType(Exception,Type));
|
||||
END;
|
||||
PROCEDURE CastToType@2(VAR Exception@1002 : DotNet "'mscorlib'.System.FormatException";Type@1007 : DotNet "'mscorlib'.System.Type") : Boolean;
|
||||
BEGIN
|
||||
Exception := OuterException;
|
||||
REPEAT
|
||||
IF Type.Equals(Exception.GetType()) THEN
|
||||
EXIT(TRUE);
|
||||
Exception := Exception.InnerException;
|
||||
UNTIL ISNULL(Exception);
|
||||
EXIT(FALSE);
|
||||
END;
|
||||
PROCEDURE Rethrow@4();
|
||||
BEGIN
|
||||
IF NOT ISNULL(OuterException.InnerException) THEN
|
||||
ERROR(OuterException.InnerException.Message);
|
||||
ERROR(OuterException.Message);
|
||||
END;
|
||||
BEGIN
|
||||
END.
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
</code></pre></div><h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>The DotNet Exception Handler codeunit has been used for the Web service integration required for:</p>
|
||||
<ol>
|
||||
<li>Payment Export from the Payment Journal for creating bank-specific payment files.</li>
|
||||
|
|
@ -429,12 +449,12 @@ END.
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>TryFunction NET Exception Handling in CAL :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/net-exception-handling-in-cal/tryfunction-net-exception-handling-in-cal/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -300,129 +300,153 @@ ALGuidelines.Dev
|
|||
<p>For instance, if a failure to establish a connection to the web service due to lack of Internet access, a <strong>WebException</strong> is thrown with the relevant error details. <strong>COD1290 Web Service Mgt.</strong> codeunit wraps up the required functionality to interact with a web service in C/AL, handling all the required plumping work to send web requests, receive web responses, and extract valid and error details from the web response.</p>
|
||||
<h3 id=code-sample>Code Sample</h3>
|
||||
<p>The “External Data Handling Codeunit” is a consumer of <strong>COD1290 Web Service Mgt.</strong> codeunit. If a runtime exception occurs, it gets handled as follows:</p>
|
||||
<pre><code>\[TryFunction\]
|
||||
PROCEDURE SendRequestToWebService@17();
|
||||
VAR
|
||||
WebRequestHelper@1000 : Codeunit 1299;
|
||||
HttpWebRequest@1007 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebRequest";
|
||||
HttpStatusCode@1002 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseHeaders@1001 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.Specialized.NameValueCollection";
|
||||
ResponseInStream@1006 : InStream;
|
||||
BEGIN
|
||||
CheckGlobals;
|
||||
BuildWebRequest(GlobalURL,HttpWebRequest);
|
||||
ResponseInStreamTempBlob.INIT;
|
||||
ResponseInStreamTempBlob.Blob.CREATEINSTREAM(ResponseInStream);
|
||||
CreateSoapRequest(HttpWebRequest.GetRequestStream,GlobalRequestBodyInStream,GlobalUsername,GlobalPassword);
|
||||
WebRequestHelper.GetWebResponse(HttpWebRequest,HttpWebResponse,ResponseInStream,HttpStatusCode,ResponseHeaders,GlobalProgressDialogEnabled);
|
||||
ExtractContentFromResponse(ResponseInStream,ResponseBodyTempBlob);
|
||||
END;
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[TryFunction]
|
||||
<span style=color:#66d9ef>PROCEDURE</span> SendRequestToWebService@<span style=color:#ae81ff>17</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
WebRequestHelper@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1299</span>;
|
||||
HttpWebRequest@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebRequest";
|
||||
HttpStatusCode@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseHeaders@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.Specialized.NameValueCollection";
|
||||
ResponseInStream@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
CheckGlobals;
|
||||
|
||||
LOCAL PROCEDURE SendDataToConversionService@1(VAR PaymentFileTempBlob@1003 : Record 99008535;BodyTempBlob@1004 : Record 99008535;PostingExch@1007 : Record 1220);
|
||||
VAR
|
||||
BankDataConvServiceSetup@1000 : Record 1260;
|
||||
WebServiceRequestMgt@1001 : Codeunit 1290;
|
||||
BodyInStream@1005 : InStream;
|
||||
ResponseInStream@1002 : InStream;
|
||||
BEGIN
|
||||
IF NOT BodyTempBlob.Blob.HASVALUE THEN
|
||||
ERROR(NoRequestBodyErr);
|
||||
PrepareSOAPRequestBody(BodyTempBlob);
|
||||
COMMIT;
|
||||
BankDataConvServiceSetup.GET;
|
||||
BodyTempBlob.Blob.CREATEINSTREAM(BodyInStream);
|
||||
WebServiceRequestMgt.SetGlobals(BodyInStream,
|
||||
BankDataConvServiceSetup."Service URL",BankDataConvServiceSetup."User Name",BankDataConvServiceSetup.GetPassword);
|
||||
IF NOT WebServiceRequestMgt.SendRequestToWebService THEN
|
||||
WebServiceRequestMgt.ProcessFaultResponse;
|
||||
WebServiceRequestMgt.GetResponseContent(ResponseInStream);
|
||||
CheckIfErrorsOccurred(ResponseInStream,PostingExch);
|
||||
ReadContentFromResponse(PaymentFileTempBlob,ResponseInStream);
|
||||
END;
|
||||
BuildWebRequest<span style=color:#f92672>(</span>GlobalURL,HttpWebRequest<span style=color:#f92672>)</span>;
|
||||
|
||||
PROCEDURE ProcessFaultResponse@15();
|
||||
VAR
|
||||
XMLDOMMgt@1006 : Codeunit 6224;
|
||||
DotNetExceptionHandler@1000 : Codeunit 1291;
|
||||
WebException@1005 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebException";
|
||||
WebExceptionStatus@1004 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebExceptionStatus";
|
||||
XmlDoc@1003 : DotNet "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument";
|
||||
HttpWebResponseError@1007 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebResponse";
|
||||
HttpStatusCode@1008 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseInputStream@1002 : InStream;
|
||||
BEGIN
|
||||
DotNetExceptionHandler.Collect;
|
||||
IF NOT DotNetExceptionHandler.CastToType(WebException,GETDOTNETTYPE(WebException)) THEN
|
||||
DotNetExceptionHandler.Rethrow;
|
||||
IF NOT WebException.Status.Equals(WebExceptionStatus.ProtocolError) THEN
|
||||
ERROR(WebException.Message);
|
||||
ResponseInputStream := WebException.Response.GetResponseStream;
|
||||
DebugLogStreamToTempFile(ResponseInputStream,'WebExceptionResponse',TempDebugLogTempBlob);
|
||||
HttpWebResponseError := WebException.Response;
|
||||
IF NOT (HttpWebResponseError.StatusCode.Equals(HttpStatusCode.Found) OR
|
||||
HttpWebResponseError.StatusCode.Equals(HttpStatusCode.InternalServerError))
|
||||
THEN
|
||||
ERROR(WebException.Message);
|
||||
XmlDoc := XmlDoc.XmlDocument;
|
||||
XmlDoc.Load(ResponseInputStream);
|
||||
ERROR(XMLDOMMgt.FindNodeTextWithNamespace(XmlDoc.DocumentElement,FaultStringXmlPathTxt,'soap',SoapNamespaceTxt));
|
||||
END;
|
||||
ResponseInStreamTempBlob<span style=color:#f92672>.</span>INIT;
|
||||
ResponseInStreamTempBlob<span style=color:#f92672>.</span><span style=color:#66d9ef>Blob</span><span style=color:#f92672>.</span>CREATEINSTREAM<span style=color:#f92672>(</span>ResponseInStream<span style=color:#f92672>)</span>;
|
||||
|
||||
OBJECT Codeunit 1291 DotNet Exception Handler
|
||||
CreateSoapRequest<span style=color:#f92672>(</span>HttpWebRequest<span style=color:#f92672>.</span>GetRequestStream,GlobalRequestBodyInStream,GlobalUsername,GlobalPassword<span style=color:#f92672>)</span>;
|
||||
|
||||
WebRequestHelper<span style=color:#f92672>.</span>GetWebResponse<span style=color:#f92672>(</span>HttpWebRequest,HttpWebResponse,ResponseInStream,
|
||||
HttpStatusCode,ResponseHeaders,GlobalProgressDialogEnabled<span style=color:#f92672>)</span>;
|
||||
|
||||
ExtractContentFromResponse<span style=color:#f92672>(</span>ResponseInStream,ResponseBodyTempBlob<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> SendDataToConversionService@<span style=color:#ae81ff>1</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> PaymentFileTempBlob@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>99008535</span>;BodyTempBlob@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>99008535</span>;PostingExch@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1220</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankDataConvServiceSetup@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>1260</span>;
|
||||
WebServiceRequestMgt@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1290</span>;
|
||||
BodyInStream@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
ResponseInStream@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> BodyTempBlob<span style=color:#f92672>.</span><span style=color:#66d9ef>Blob</span><span style=color:#f92672>.</span>HASVALUE <span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>NoRequestBodyErr<span style=color:#f92672>)</span>;
|
||||
|
||||
PrepareSOAPRequestBody<span style=color:#f92672>(</span>BodyTempBlob<span style=color:#f92672>)</span>;
|
||||
|
||||
COMMIT;
|
||||
|
||||
BankDataConvServiceSetup<span style=color:#f92672>.</span>GET;
|
||||
BodyTempBlob<span style=color:#f92672>.</span><span style=color:#66d9ef>Blob</span><span style=color:#f92672>.</span>CREATEINSTREAM<span style=color:#f92672>(</span>BodyInStream<span style=color:#f92672>)</span>;
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>SetGlobals<span style=color:#f92672>(</span>BodyInStream,BankDataConvServiceSetup<span style=color:#f92672>.</span>"Service URL",
|
||||
BankDataConvServiceSetup<span style=color:#f92672>.</span>"User Name",BankDataConvServiceSetup<span style=color:#f92672>.</span>GetPassword<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> WebServiceRequestMgt<span style=color:#f92672>.</span>SendRequestToWebService <span style=color:#66d9ef>THEN</span>
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>ProcessFaultResponse;
|
||||
|
||||
WebServiceRequestMgt<span style=color:#f92672>.</span>GetResponseContent<span style=color:#f92672>(</span>ResponseInStream<span style=color:#f92672>)</span>;
|
||||
|
||||
CheckIfErrorsOccurred<span style=color:#f92672>(</span>ResponseInStream,PostingExch<span style=color:#f92672>)</span>;
|
||||
|
||||
ReadContentFromResponse<span style=color:#f92672>(</span>PaymentFileTempBlob,ResponseInStream<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> ProcessFaultResponse@<span style=color:#ae81ff>15</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
XMLDOMMgt@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>6224</span>;
|
||||
DotNetExceptionHandler@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1291</span>;
|
||||
WebException@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebException";
|
||||
WebExceptionStatus@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebExceptionStatus";
|
||||
XmlDoc@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>DotNet</span> "'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument";
|
||||
HttpWebResponseError@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpWebResponse";
|
||||
HttpStatusCode@<span style=color:#ae81ff>1008</span> : <span style=color:#66d9ef>DotNet</span> "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.HttpStatusCode";
|
||||
ResponseInputStream@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>InStream</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
DotNetExceptionHandler<span style=color:#f92672>.</span>Collect;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> DotNetExceptionHandler<span style=color:#f92672>.</span>CastToType<span style=color:#f92672>(</span>WebException,GETDOTNETTYPE<span style=color:#f92672>(</span>WebException<span style=color:#f92672>)) </span><span style=color:#66d9ef>THEN</span>
|
||||
DotNetExceptionHandler<span style=color:#f92672>.</span>Rethrow;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> WebException<span style=color:#f92672>.</span>Status<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>WebExceptionStatus<span style=color:#f92672>.</span>ProtocolError<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>WebException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
ResponseInputStream <span style=color:#f92672>:=</span> WebException<span style=color:#f92672>.</span>Response<span style=color:#f92672>.</span>GetResponseStream;
|
||||
DebugLogStreamToTempFile<span style=color:#f92672>(</span>ResponseInputStream,<span style=color:#e6db74>'WebExceptionResponse'</span>,TempDebugLogTempBlob<span style=color:#f92672>)</span>;
|
||||
|
||||
HttpWebResponseError <span style=color:#f92672>:=</span> WebException<span style=color:#f92672>.</span>Response;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> <span style=color:#f92672>(</span>HttpWebResponseError<span style=color:#f92672>.</span>StatusCode<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>HttpStatusCode<span style=color:#f92672>.</span>Found<span style=color:#f92672>) </span><span style=color:#f92672>OR</span>
|
||||
HttpWebResponseError<span style=color:#f92672>.</span>StatusCode<span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>HttpStatusCode<span style=color:#f92672>.</span>InternalServerError<span style=color:#f92672>))
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>WebException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
XmlDoc <span style=color:#f92672>:=</span> XmlDoc<span style=color:#f92672>.</span><span style=color:#66d9ef>XmlDocument</span>;
|
||||
XmlDoc<span style=color:#f92672>.</span>Load<span style=color:#f92672>(</span>ResponseInputStream<span style=color:#f92672>)</span>;
|
||||
|
||||
ERROR<span style=color:#f92672>(</span>XMLDOMMgt<span style=color:#f92672>.</span>FindNodeTextWithNamespace<span style=color:#f92672>(</span>XmlDoc<span style=color:#f92672>.</span>DocumentElement,FaultStringXmlPathTxt,<span style=color:#e6db74>'soap'</span>,SoapNamespaceTxt<span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OBJECT <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>1291</span> <span style=color:#66d9ef>DotNet</span> Exception Handler
|
||||
{
|
||||
OBJECT-PROPERTIES
|
||||
{
|
||||
Date=;
|
||||
Time=;
|
||||
Version List=;
|
||||
OBJECT<span style=color:#f92672>-</span>PROPERTIES
|
||||
{
|
||||
<span style=color:#66d9ef>Date</span>=;
|
||||
<span style=color:#66d9ef>Time</span>=;
|
||||
<span style=color:#66d9ef>Version</span> <span style=color:#66d9ef>List</span>=;
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
OnRun=<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
}
|
||||
<span style=color:#66d9ef>CODE</span>
|
||||
{
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
OuterException@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Exception";
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Catch@<span style=color:#ae81ff>3</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Exception@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";<span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
Collect;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> CastToType<span style=color:#f92672>(</span>Exception,<span style=color:#66d9ef>Type</span><span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
Rethrow;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Collect@<span style=color:#ae81ff>1</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
OuterException <span style=color:#f92672>:=</span> GETLASTERROROBJECT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> TryCastToType@<span style=color:#ae81ff>5</span><span style=color:#f92672>(</span><span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
Exception@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>CastToType<span style=color:#f92672>(</span>Exception,<span style=color:#66d9ef>Type</span><span style=color:#f92672>))</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> CastToType@<span style=color:#ae81ff>2</span><span style=color:#f92672>(</span><span style=color:#66d9ef>VAR</span> Exception@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.FormatException";<span style=color:#66d9ef>Type</span>@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>DotNet</span> "'mscorlib'.System.Type"<span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
Exception <span style=color:#f92672>:=</span> OuterException;
|
||||
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#66d9ef>Type</span><span style=color:#f92672>.</span>Equals<span style=color:#f92672>(</span>Exception<span style=color:#f92672>.</span>GetType<span style=color:#f92672>()) </span><span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
Exception <span style=color:#f92672>:=</span> Exception<span style=color:#f92672>.</span>InnerException;
|
||||
<span style=color:#66d9ef>UNTIL</span> ISNULL<span style=color:#f92672>(</span>Exception<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>PROCEDURE</span> Rethrow@<span style=color:#ae81ff>4</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> ISNULL<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>InnerException<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>InnerException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
|
||||
ERROR<span style=color:#f92672>(</span>OuterException<span style=color:#f92672>.</span>Message<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>END</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672> </span>}
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
OnRun=BEGIN
|
||||
END;
|
||||
}
|
||||
CODE
|
||||
{
|
||||
VAR
|
||||
OuterException@1000 : DotNet "'mscorlib'.System.Exception";
|
||||
PROCEDURE Catch@3(VAR Exception@1002 : DotNet "'mscorlib'.System.FormatException";Type@1007 : DotNet "'mscorlib'.System.Type");
|
||||
BEGIN
|
||||
Collect;
|
||||
IF NOT CastToType(Exception,Type) THEN
|
||||
Rethrow;
|
||||
END;
|
||||
PROCEDURE Collect@1();
|
||||
BEGIN
|
||||
OuterException := GETLASTERROROBJECT;
|
||||
END;
|
||||
PROCEDURE TryCastToType@5(Type@1000 : DotNet "'mscorlib'.System.Type") : Boolean;
|
||||
VAR
|
||||
Exception@1001 : DotNet "'mscorlib'.System.FormatException";
|
||||
BEGIN
|
||||
EXIT(CastToType(Exception,Type));
|
||||
END;
|
||||
PROCEDURE CastToType@2(VAR Exception@1002 : DotNet "'mscorlib'.System.FormatException";Type@1007 : DotNet "'mscorlib'.System.Type") : Boolean;
|
||||
BEGIN
|
||||
Exception := OuterException;
|
||||
REPEAT
|
||||
IF Type.Equals(Exception.GetType()) THEN
|
||||
EXIT(TRUE);
|
||||
Exception := Exception.InnerException;
|
||||
UNTIL ISNULL(Exception);
|
||||
EXIT(FALSE);
|
||||
END;
|
||||
PROCEDURE Rethrow@4();
|
||||
BEGIN
|
||||
IF NOT ISNULL(OuterException.InnerException) THEN
|
||||
ERROR(OuterException.InnerException.Message);
|
||||
ERROR(OuterException.Message);
|
||||
END;
|
||||
BEGIN
|
||||
END.
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
</code></pre></div><h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>The <strong>CO1291 DotNet Exception Handler</strong> codeunit has been used for the Web service integration required for:</p>
|
||||
<ol>
|
||||
<li>Payment Export from the Payment Journal for creating bank-specific payment files.</li>
|
||||
|
|
@ -441,12 +465,12 @@ END.
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>No Series :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/no-series/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -261,7 +261,7 @@ ALGuidelines.Dev
|
|||
<li><a href=#nav-usages>NAV Usages</a>
|
||||
<ul>
|
||||
<li><a href=#sales-and-receivables>Sales and Receivables</a></li>
|
||||
<li><a href=#heading></a></li>
|
||||
<li><a href=#field-no>Field “No.”</a></li>
|
||||
<li><a href=#field-no-series>Field “No. Series”</a></li>
|
||||
<li><a href=#assistedit>AssistEdit</a></li>
|
||||
<li><a href=#oninsert>OnInsert</a></li>
|
||||
|
|
@ -292,68 +292,133 @@ ALGuidelines.Dev
|
|||
<p>From the implementation point of view, a number series is a record in the table 308 - “No. Series”.</p>
|
||||
<p><a href=5661.1.png><img src=5661.1.png alt=" "></a></p>
|
||||
<p>The most relevant fields are:</p>
|
||||
<p>Code</p>
|
||||
<p>Code 10</p>
|
||||
<p>Used to identify the number series in further places where it will be used.</p>
|
||||
<p>Default Nos.</p>
|
||||
<p>Boolean</p>
|
||||
<p>The boolean <strong>Default Nos.</strong> decides whether this number series can use automatic numbering. If false, then the user is expected to manually look up the No. field and select it from the number series.</p>
|
||||
<p>Manual Nos.</p>
|
||||
<p>Boolean</p>
|
||||
<p>If the <strong>Manual Nos.</strong> is Yes, then the used will be allowed to manually type the value of the next number (“No.") field.</p>
|
||||
<p>Date Order</p>
|
||||
<p>Boolean</p>
|
||||
<p><strong>Date Order</strong> is used to decide whether or not the numbers from the range are assigned chronologically.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Code</td>
|
||||
<td>Code 10</td>
|
||||
<td>Used to identify the number series in further places where it will be used.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Default Nos.</td>
|
||||
<td>Boolean</td>
|
||||
<td>The boolean <strong>Default Nos.</strong> decides whether this number series can use automatic numbering. If false, then the user is expected to manually look up the No. field and select it from the number series.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Manual Nos.</td>
|
||||
<td>Boolean</td>
|
||||
<td>If the <strong>Manual Nos.</strong> is Yes, then the used will be allowed to manually type the value of the next number (“No.") field.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date Order</td>
|
||||
<td>Boolean</td>
|
||||
<td><strong>Date Order</strong> is used to decide whether or not the numbers from the range are assigned chronologically.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id=number-series-sequence>Number Series sequence</h3>
|
||||
<p>The sequence definition is found in table 309 - No. Series Line. Contains the explicit definition of the series, for example a series called BANK, could start with BANK001 and increase incrementally by one, in the sequence BANK001, BANK002, BANK003, …. Until the last number BANK999. When hitting the number BANK990, the user will receive a warning that the series is about to be exhausted and it must either be increased, or a new series should be assigned.</p>
|
||||
<p><a href=1452.2.png><img src=1452.2.png alt=" "></a></p>
|
||||
<p><a href=3527.3.png><img src=3527.3.png alt=" "></a></p>
|
||||
<p>The most relevant fields are:</p>
|
||||
<p>Series Code</p>
|
||||
<p>Code 10</p>
|
||||
<p>Links it to the number series defined in table 308.</p>
|
||||
<p>Starting No.</p>
|
||||
<p>Integer</p>
|
||||
<p>This is the first number in the sequence, for a book indexing application it can be BOOK0001.</p>
|
||||
<p>Ending No.</p>
|
||||
<p>Integer</p>
|
||||
<p>The last number in the sequence, for example BOOK5000.</p>
|
||||
<p>Warning No.</p>
|
||||
<p>Integer</p>
|
||||
<p>When this number is reached, the user will see a warning message stating that the number series is running out of assignable numbers.</p>
|
||||
<p>Increment-by No.</p>
|
||||
<p>Integer</p>
|
||||
<p>The value for incrementing the numeric part of the series.</p>
|
||||
<p>Last No. Used</p>
|
||||
<p>Code 20</p>
|
||||
<p>The last number from the sequence that was assigned.</p>
|
||||
<p>Last Date Used</p>
|
||||
<p>Date</p>
|
||||
<p>Stating when the last number was assigned.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Series Code</td>
|
||||
<td>Code 10</td>
|
||||
<td>Links it to the number series defined in table 308.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Starting No.</td>
|
||||
<td>Integer</td>
|
||||
<td>This is the first number in the sequence, for a book indexing application it can be BOOK0001.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ending No.</td>
|
||||
<td>Integer</td>
|
||||
<td>The last number in the sequence, for example BOOK5000.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Warning No.</td>
|
||||
<td>Integer</td>
|
||||
<td>When this number is reached, the user will see a warning message stating that the number series is running out of assignable numbers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Increment-by No.</td>
|
||||
<td>Integer</td>
|
||||
<td>The value for incrementing the numeric part of the series.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last No. Used</td>
|
||||
<td>Code 20</td>
|
||||
<td>The last number from the sequence that was assigned.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last Date Used</td>
|
||||
<td>Date</td>
|
||||
<td>Stating when the last number was assigned.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id=add-the-default-number-series-to-the-setup>Add the default number series to the setup</h3>
|
||||
<p>Various series of numbers can be defined as seen above. For example, a library can have a number series for indexing rental of each of the following: books, movies, music, video. The books series can be split by domain, for example a series BOOKSCIFI can have BOOK0001…BOOK1500, then BOOKTECH can use the sequence BOOK1501…BOOK4000 and so on.</p>
|
||||
<p>The default number series for a certain application area is typically stored in the domain setup table. For example, NAV Demo Database stores the default Item number series in the Inventory Setup table 313. This means that you will need to add the Number Series fields in your setup table and ensure that before the customer starts using the solution, the number series is created and added to the setup defaults.</p>
|
||||
<h3 id=how-to-use-the-number-series>How to use the Number Series</h3>
|
||||
<p>The table which will host the number from the number series, needs the following fields:</p>
|
||||
<p>No.</p>
|
||||
<p>Code 20</p>
|
||||
<p>Contains the auto-generated sequential number.</p>
|
||||
<p>No. Series</p>
|
||||
<p>Code 10</p>
|
||||
<p>The number series definition, which decides what the next No. will be.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>No.</td>
|
||||
<td>Code 20</td>
|
||||
<td>Contains the auto-generated sequential number.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. Series</td>
|
||||
<td>Code 10</td>
|
||||
<td>The number series definition, which decides what the next No. will be.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>And the code to make the number series alive:</p>
|
||||
<p><strong>OnInsert</strong></p>
|
||||
<p>OnInsert()</p>
|
||||
<p>IF “No.” = '' THEN</p>
|
||||
<p>NoSeriesMgt.InitSeries(DefaultNoSeriesCode,OldNoSeriesCode,NewDate,NewNo,NewNoSeriesCode);</p>
|
||||
<p><strong>Field “No."</strong></p>
|
||||
<p>No. - OnValidate()</p>
|
||||
<p>IF “No.” <> xRec.“No.” THEN BEGIN // Validate that “No.” corresponds to the current No. Series rules NoSeriesMgt.TestManual(DefaultNoSeriesCode); “No. Series” := ‘'; END;</p>
|
||||
<p><strong>AssistEdit</strong></p>
|
||||
<p>AssistEdit() : Boolean</p>
|
||||
<p>IF “No.” = '’ THEN</p>
|
||||
<p>NoSeriesMgt.InitSeries(DefaultNoSeriesCode,OldNoSeriesCode,NewDate,NewNo,NewNoSeriesCode);</p>
|
||||
<p>Where:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OnInsert<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> "No." = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
NoSeriesMgt<span style=color:#f92672>.</span>InitSeries<span style=color:#f92672>(</span>DefaultNoSeriesCode,OldNoSeriesCode,NewDate,NewNo,NewNoSeriesCode<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p><strong>Field “No."</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>No<span style=color:#f92672>. </span>- OnValidate<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> "No." <> xRec<span style=color:#f92672>.</span>"No." <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span> <span style=color:#75715e>// Validate that "No." corresponds to the current No. Series rules
|
||||
</span><span style=color:#75715e></span> NoSeriesMgt<span style=color:#f92672>.</span>TestManual<span style=color:#f92672>(</span>DefaultNoSeriesCode<span style=color:#f92672>)</span>;
|
||||
"No. Series" <span style=color:#f92672>:=</span> <span style=color:#e6db74>''</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><strong>AssistEdit</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>AssistEdit<span style=color:#f92672>() </span>: <span style=color:#66d9ef>Boolean</span>
|
||||
|
||||
<span style=color:#66d9ef>IF</span> "No." = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
NoSeriesMgt<span style=color:#f92672>.</span>InitSeries<span style=color:#f92672>(</span>DefaultNoSeriesCode,OldNoSeriesCode,NewDate,NewNo,NewNoSeriesCode<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Where:</p>
|
||||
<ul>
|
||||
<li><strong>DefaultNoSeriesCode</strong> is typically found in the application domain setup table.</li>
|
||||
<li><strong>OldNoSeriesCode</strong> is typically the previous value of the “No. Series” code, which is found in <strong>xRec.“No. Series”</strong></li>
|
||||
|
|
@ -365,51 +430,61 @@ ALGuidelines.Dev
|
|||
<h3 id=sales-and-receivables>Sales and Receivables</h3>
|
||||
<p>The setup table 311 (Sales & Receivables Setup) contains the default number series to be used in the whole application domain. In the demo data, some of the series defined here are: Customer Nos., Quote Nos., Order Nos., Invoice Nos., Posted Invoice Nos., Credit Memo Nos., Posted Credit Memo Nos., etc. Those number series are dimensioned for the needs of a typical small to medium sized company, however, various business have different patterns (for example, posting an unusual high number of invoices). In this case, the number series should be adjusted accordingly to make space for the customized company needs.</p>
|
||||
<p>The default number series defined in the setup is then used in the individual tables. For example, table 18 - Customer, has</p>
|
||||
<h3 id=heading></h3>
|
||||
<p>Field “No.”</p>
|
||||
<p>{ 1 ; ;No. ;Code20 ;AltSearchField=Search Name;</p>
|
||||
<p>OnValidate=</p>
|
||||
<p>BEGIN</p>
|
||||
<p>IF “No.” <> xRec.“No.” THEN BEGIN</p>
|
||||
<p>SalesSetup.GET;</p>
|
||||
<p>NoSeriesMgt.TestManual(SalesSetup.“Customer Nos.");</p>
|
||||
<p>“No. Series” := ‘';</p>
|
||||
<p>END;</p>
|
||||
<p>IF “Invoice Disc. Code” = '’ THEN</p>
|
||||
<p>“Invoice Disc. Code” := “No.";</p>
|
||||
<p>END;</p>
|
||||
<p>}</p>
|
||||
<h3 id=field-no-series>Field “No. Series”</h3>
|
||||
<p>{ 107 ; ;No. Series ;Code10 ;TableRelation=“No. Series”; Editable=No }</p>
|
||||
<h3 id=assistedit>AssistEdit</h3>
|
||||
<p>PROCEDURE AssistEdit@2(OldCust@1000 : Record 18) : Boolean;</p>
|
||||
<p>VAR Cust@1001 : Record 18;</p>
|
||||
<p>BEGIN</p>
|
||||
<p>WITH Cust DO BEGIN</p>
|
||||
<p>Cust := Rec;</p>
|
||||
<p>SalesSetup.GET;</p>
|
||||
<p>SalesSetup.TESTFIELD(“Customer Nos.");</p>
|
||||
<p>IF NoSeriesMgt.SelectSeries(SalesSetup.“Customer Nos.",OldCust.“No. Series”,“No. Series”) THEN BEGIN</p>
|
||||
<p>NoSeriesMgt.SetSeries(“No.");</p>
|
||||
<p>Rec := Cust;</p>
|
||||
<p>EXIT(TRUE);</p>
|
||||
<p>END;</p>
|
||||
<p>END;</p>
|
||||
<p>END;</p>
|
||||
<h3 id=oninsert>OnInsert</h3>
|
||||
<p>OnInsert=<br>
|
||||
BEGIN</p>
|
||||
<p>IF “No.” = '' THEN BEGIN</p>
|
||||
<p>SalesSetup.GET;</p>
|
||||
<p>SalesSetup.TESTFIELD(“Customer Nos.");</p>
|
||||
<p>NoSeriesMgt.InitSeries(SalesSetup.“Customer Nos.",xRec.“No. Series”,0D,“No.”,“No. Series”);</p>
|
||||
<p>END;</p>
|
||||
<p>…</p>
|
||||
<p>END</p>
|
||||
<p>To run the AssistEdit procedure, include this code on the No. - OnAssistEdit() trigger of the Page:</p>
|
||||
<h3 id=field-no>Field “No.”</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>{ <span style=color:#ae81ff>1</span> ; ;No<span style=color:#f92672>. </span>;Code20 ;AltSearchField=Search Name;
|
||||
|
||||
OnValidate=
|
||||
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> "No." <> xRec<span style=color:#f92672>.</span>"No." <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
SalesSetup<span style=color:#f92672>.</span>GET;
|
||||
|
||||
NoSeriesMgt<span style=color:#f92672>.</span>TestManual<span style=color:#f92672>(</span>SalesSetup<span style=color:#f92672>.</span>"Customer Nos."<span style=color:#f92672>)</span>;
|
||||
|
||||
"No. Series" <span style=color:#f92672>:=</span> <span style=color:#e6db74>''</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> "Invoice Disc. Code" = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
"Invoice Disc. Code" <span style=color:#f92672>:=</span> "No.";
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
}
|
||||
</code></pre></div><h3 id=field-no-series>Field “No. Series”</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>{ <span style=color:#ae81ff>107</span> ; ;No<span style=color:#f92672>. </span>Series ;Code10 ;TableRelation="No. Series"; Editable=No }
|
||||
</code></pre></div><h3 id=assistedit>AssistEdit</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> AssistEdit@<span style=color:#ae81ff>2</span><span style=color:#f92672>(</span>OldCust@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>18</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
Cust@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>18</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>WITH</span> Cust <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
Cust <span style=color:#f92672>:=</span> Rec;
|
||||
SalesSetup<span style=color:#f92672>.</span>GET;
|
||||
|
||||
SalesSetup<span style=color:#f92672>.</span><span style=color:#66d9ef>TESTFIELD</span><span style=color:#f92672>(</span>"Customer Nos."<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> NoSeriesMgt<span style=color:#f92672>.</span>SelectSeries<span style=color:#f92672>(</span>SalesSetup<span style=color:#f92672>.</span>"Customer Nos.",OldCust<span style=color:#f92672>.</span>"No. Series","No. Series"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
NoSeriesMgt<span style=color:#f92672>.</span>SetSeries<span style=color:#f92672>(</span>"No."<span style=color:#f92672>)</span>;
|
||||
Rec <span style=color:#f92672>:=</span> Cust;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><h3 id=oninsert>OnInsert</h3>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OnInsert=
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> "No." = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
SalesSetup<span style=color:#f92672>.</span>GET;
|
||||
|
||||
SalesSetup<span style=color:#f92672>.</span><span style=color:#66d9ef>TESTFIELD</span><span style=color:#f92672>(</span>"Customer Nos."<span style=color:#f92672>)</span>;
|
||||
|
||||
NoSeriesMgt<span style=color:#f92672>.</span>InitSeries<span style=color:#f92672>(</span>SalesSetup<span style=color:#f92672>.</span>"Customer Nos.",xRec<span style=color:#f92672>.</span>"No. Series",0D,"No.","No. Series"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span>
|
||||
</code></pre></div><p>To run the AssistEdit procedure, include this code on the No. - OnAssistEdit() trigger of the Page:</p>
|
||||
<h3 id=no---onassistedit>No. - OnAssistEdit()</h3>
|
||||
<p>IF AssistEdit(xRec) THEN</p>
|
||||
<p>CurrPage.UPDATE;</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> AssistEdit<span style=color:#f92672>(</span>xRec<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
CurrPage<span style=color:#f92672>.</span>UPDATE;
|
||||
</code></pre></div>
|
||||
<div style=position:relative;padding-bottom:56.25%;height:0;overflow:hidden>
|
||||
<iframe src=https://www.youtube.com/embed/1lG9rY_dmM4 style=position:absolute;top:0;left:0;width:100%;height:100%;border:0 allowfullscreen title="YouTube Video"></iframe>
|
||||
</div>
|
||||
|
|
@ -425,12 +500,12 @@ BEGIN</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>In-context Notifications :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/notifications/in-context-notifications/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -262,6 +262,8 @@ ALGuidelines.Dev
|
|||
</ul>
|
||||
</li>
|
||||
<li><a href=#turning-notifications-on-or-off-and-controlling-when-they-are-sent>Turning notifications on or off, and controlling when they are sent</a></li>
|
||||
<li><a href=#nav-specific-usages>NAV specific usages</a></li>
|
||||
<li><a href=#best-practices>Best practices</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -306,7 +308,7 @@ ALGuidelines.Dev
|
|||
<p>The ID is an optional parameter for the notification object that tracks the object in communications between the client and the server. Notifications have unique IDs that can be hard coded as GUIDs, as shown in Figure 5. A GUID can be generated using <a href=https://msdn.microsoft.com/en-us/library/dd339033.aspx>the CREATEGUID system function</a>.</p>
|
||||
<p><strong>COD 311: Item-Check Avail.</strong></p>
|
||||
<p><strong>GetItemAvailabilityNotificationId</strong></p>
|
||||
<p>EXIT(‘2712AD06-C48B-4C20-820E-347A60C9AD00’);****</p>
|
||||
<p>EXIT(‘2712AD06-C48B-4C20-820E-347A60C9AD00’);</p>
|
||||
<p>Figure 5. Uniquely identifying a notification</p>
|
||||
<p>If the call to set ID is skipped, sending the notification creates a new notification with an ID that is generated at run-time instead of updating a notification that is already displayed (if present) with the ID.</p>
|
||||
<h3 id=including-messages-notifications>Including messages notifications</h3>
|
||||
|
|
@ -385,7 +387,7 @@ ALGuidelines.Dev
|
|||
<li><strong>OnStateChanged</strong> event should be subscribed to if the developer needs to do something additional when changing the state of a notification, such as turn on another notification.</li>
|
||||
</ol>
|
||||
<p>The ability to turn notifications on or off is not required. If skipped, the notification is always shown when the condition that triggers it is met, and a user cannot turn it off.</p>
|
||||
<h1 id=nav-specific-usages>NAV specific usages</h1>
|
||||
<h2 id=nav-specific-usages>NAV specific usages</h2>
|
||||
<p>For examples of how these objects are used in Dynamics NAV, look at the code for the following objects:</p>
|
||||
<ol>
|
||||
<li>Codeunit 1802 Data Migration Notifier</li>
|
||||
|
|
@ -394,7 +396,7 @@ ALGuidelines.Dev
|
|||
<li>Codeunit 1854 Item Sales Forecast Notifier (in SalesAndInventoryForecast extension)</li>
|
||||
<li>Codeunit 1852 Item Sales Forecast Scheduler (in SalesAndInventoryForecast extension)</li>
|
||||
</ol>
|
||||
<h1 id=best-practices>Best practices</h1>
|
||||
<h2 id=best-practices>Best practices</h2>
|
||||
<p>The following list summarizes best practices for creating notifications:</p>
|
||||
<ol>
|
||||
<li>Do not set data on the notification that you will not use in the method invoked from the action button.</li>
|
||||
|
|
@ -414,12 +416,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/notifications/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Notifications :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/notifications/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -268,12 +268,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Notification Lifecycle Management Pattern :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/notifications/notification-lifecycle-management-pattern/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -263,48 +263,49 @@ ALGuidelines.Dev
|
|||
<p> </p>
|
||||
<p><strong>Description</strong></p>
|
||||
<p>Notifications are easy to use in a wide range of cases. Instead of using notifications in a fire-and-forget way, we need to track them so that we can recall them if we need to.</p>
|
||||
<p>If we can have only one notification on a given page, an easy and efficient solution is to use a predefined Notification ID, as suggested in the “Using In-context Notifications” pattern.</p>
|
||||
<p>If we can have only one notification on a given page, an easy and efficient solution is to use a predefined Notification ID, as suggested in the <a href=/navpatterns/1-patterns/notifications/in-context-notifications/>“Using In-context Notifications”</a> pattern.</p>
|
||||
<p>However, some cases can be more complicated. For example, when you are adding lines to a table, what if several lines raise individual notifications? Using the same notification ID for each notification will no longer work because the latest notification overwrites the previous ones. Only one notification for a given notification ID can exist, and only the notification message would be updated. This is illustrated in Figure 1.</p>
|
||||
<p><a href=4807.1st-notification.PNG><img src=4807.1st-notification.PNG alt=" "></a></p>
|
||||
<p><em>Figure 1: Notification that an item that is not in stock. The notification ID is a predefined GUID, 2712AD06-C48B-4C20-820E-347A60C9AD00, for example.</em></p>
|
||||
<p><a href=8512.2nd-notification.PNG><img src=8512.2nd-notification.PNG alt=" "></a></p>
|
||||
<p><em>Figure 2: You add a second item that is not in stock. the notification is fired with the same GUID, 2712AD06-C48B-4C20-820E-347A60C9AD00, for example. The previous notification is overwritten.</em></p>
|
||||
<p>Here is the code for this behavior:</p>
|
||||
<pre><code>LOCAL PROCEDURE CreateAndSendNotification@23(UnitOfMeasureCode@1010 : Code\[20\];InventoryQty@1009 : Decimal;GrossReq@1008 : Decimal;ReservedReq@1007 : Decimal;SchedRcpt@1006 : Decimal;ReservedRcpt@1005 : Decimal;CurrentQuantity@1004 : Decimal;CurrentReservedQty@1003 : Decimal;TotalQuantity@1002 : Decimal;EarliestAvailDate@1001 : Date) : Boolean;
|
||||
VAR
|
||||
ItemAvailabilityCheck@1011 : Page 1872;
|
||||
AvailabilityCheckNotification@1000 : Notification;
|
||||
BEGIN
|
||||
**AvailabilityCheckNotification.ID(GetItemAvailabilityNotificationId);**
|
||||
AvailabilityCheckNotification.MESSAGE(STRSUBSTNO(NotificationMsg,ItemNo));
|
||||
AvailabilityCheckNotification.SCOPE(NOTIFICATIONSCOPE::LocalScope);
|
||||
AvailabilityCheckNotification.ADDACTION(DetailsTxt,CODEUNIT::"Item-Check Avail.",'ShowNotificationDetails');
|
||||
ItemAvailabilityCheck.PopulateDataOnNotification(AvailabilityCheckNotification,ItemNo,UnitOfMeasureCode,InventoryQty,GrossReq,ReservedReq,SchedRcpt,ReservedRcpt,CurrentQuantity,CurrentReservedQty,TotalQuantity,EarliestAvailDate);
|
||||
AvailabilityCheckNotification.SEND;
|
||||
EXIT(FALSE);
|
||||
END;
|
||||
LOCAL PROCEDURE **GetItemAvailabilityNotificationId**@27() : GUID;
|
||||
BEGIN
|
||||
**EXIT('2712AD06-C48B-4C20-820E-347A60C9AD00');**
|
||||
END;
|
||||
</code></pre>
|
||||
<p>An easy fix would be to dynamically generate the notification ID. However, what if you fix the issue that triggered the notification?</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> CreateAndSendNotification@<span style=color:#ae81ff>23</span><span style=color:#f92672>(</span>UnitOfMeasureCode@<span style=color:#ae81ff>1010</span> : <span style=color:#66d9ef>Code</span>[<span style=color:#ae81ff>20</span>];InventoryQty@<span style=color:#ae81ff>1009</span> : <span style=color:#66d9ef>Decimal</span>;GrossReq@<span style=color:#ae81ff>1008</span> : <span style=color:#66d9ef>Decimal</span>;ReservedReq@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Decimal</span>;SchedRcpt@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>Decimal</span>;ReservedRcpt@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>Decimal</span>;CurrentQuantity@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Decimal</span>;CurrentReservedQty@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Decimal</span>;TotalQuantity@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>Decimal</span>;EarliestAvailDate@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Date</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
ItemAvailabilityCheck@<span style=color:#ae81ff>1011</span> : <span style=color:#66d9ef>Page</span> <span style=color:#ae81ff>1872</span>;
|
||||
AvailabilityCheckNotification@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Notification</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>ID<span style=color:#f92672>(</span>GetItemAvailabilityNotificationId<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>MESSAGE<span style=color:#f92672>(</span>STRSUBSTNO<span style=color:#f92672>(</span>NotificationMsg,ItemNo<span style=color:#f92672>))</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>SCOPE<span style=color:#f92672>(</span><span style=color:#66d9ef>NOTIFICATIONSCOPE</span>::LocalScope<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>ADDACTION<span style=color:#f92672>(</span>DetailsTxt,<span style=color:#66d9ef>CODEUNIT</span>::"Item-Check Avail.",<span style=color:#e6db74>'ShowNotificationDetails'</span><span style=color:#f92672>)</span>;
|
||||
|
||||
ItemAvailabilityCheck<span style=color:#f92672>.</span>PopulateDataOnNotification<span style=color:#f92672>(</span>AvailabilityCheckNotification,ItemNo,UnitOfMeasureCode,InventoryQty,GrossReq,ReservedReq,SchedRcpt,ReservedRcpt,CurrentQuantity,CurrentReservedQty,TotalQuantity,EarliestAvailDate<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>SEND;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> **GetItemAvailabilityNotificationId**@<span style=color:#ae81ff>27</span><span style=color:#f92672>() </span>: <span style=color:#66d9ef>GUID</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span><span style=color:#e6db74>'2712AD06-C48B-4C20-820E-347A60C9AD00'</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>An easy fix would be to dynamically generate the notification ID. However, what if you fix the issue that triggered the notification?</p>
|
||||
<p>Here is the code for this possible fix:</p>
|
||||
<pre><code>LOCAL PROCEDURE CreateAndSendNotification@23(UnitOfMeasureCode@1010 : Code\[20\];InventoryQty@1009 : Decimal;GrossReq@1008 : Decimal;ReservedReq@1007 : Decimal;SchedRcpt@1006 : Decimal;ReservedRcpt@1005 : Decimal;CurrentQuantity@1004 : Decimal;CurrentReservedQty@1003 : Decimal;TotalQuantity@1002 : Decimal;EarliestAvailDate@1001 : Date) : Boolean;
|
||||
VAR
|
||||
ItemAvailabilityCheck@1011 : Page 1872;
|
||||
AvailabilityCheckNotification@1000 : Notification;
|
||||
BEGIN
|
||||
**AvailabilityCheckNotification.ID(CREATEGUID);**
|
||||
AvailabilityCheckNotification.MESSAGE(STRSUBSTNO(NotificationMsg,ItemNo));
|
||||
AvailabilityCheckNotification.SCOPE(NOTIFICATIONSCOPE::LocalScope);
|
||||
AvailabilityCheckNotification.ADDACTION(DetailsTxt,CODEUNIT::"Item-Check Avail.",'ShowNotificationDetails');
|
||||
ItemAvailabilityCheck.PopulateDataOnNotification(AvailabilityCheckNotification,ItemNo,UnitOfMeasureCode,InventoryQty,GrossReq,ReservedReq,SchedRcpt,ReservedRcpt,CurrentQuantity,CurrentReservedQty,TotalQuantity,EarliestAvailDate);
|
||||
AvailabilityCheckNotification.SEND;
|
||||
EXIT(FALSE);
|
||||
END;
|
||||
</code></pre>
|
||||
<p>Now, notifications do not replace each other, but we cannot recall them because we do not track each notification ID.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> CreateAndSendNotification@<span style=color:#ae81ff>23</span><span style=color:#f92672>(</span>UnitOfMeasureCode@<span style=color:#ae81ff>1010</span> : <span style=color:#66d9ef>Code</span>[<span style=color:#ae81ff>20</span>];InventoryQty@<span style=color:#ae81ff>1009</span> : <span style=color:#66d9ef>Decimal</span>;GrossReq@<span style=color:#ae81ff>1008</span> : <span style=color:#66d9ef>Decimal</span>;ReservedReq@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Decimal</span>;SchedRcpt@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>Decimal</span>;ReservedRcpt@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>Decimal</span>;CurrentQuantity@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Decimal</span>;CurrentReservedQty@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Decimal</span>;TotalQuantity@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>Decimal</span>;EarliestAvailDate@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Date</span><span style=color:#f92672>) </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
ItemAvailabilityCheck@<span style=color:#ae81ff>1011</span> : <span style=color:#66d9ef>Page</span> <span style=color:#ae81ff>1872</span>;
|
||||
AvailabilityCheckNotification@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Notification</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>ID<span style=color:#f92672>(</span>CREATEGUID<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>MESSAGE<span style=color:#f92672>(</span>STRSUBSTNO<span style=color:#f92672>(</span>NotificationMsg,ItemNo<span style=color:#f92672>))</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>SCOPE<span style=color:#f92672>(</span><span style=color:#66d9ef>NOTIFICATIONSCOPE</span>::LocalScope<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>ADDACTION<span style=color:#f92672>(</span>DetailsTxt,<span style=color:#66d9ef>CODEUNIT</span>::"Item-Check Avail.",<span style=color:#e6db74>'ShowNotificationDetails'</span><span style=color:#f92672>)</span>;
|
||||
|
||||
ItemAvailabilityCheck<span style=color:#f92672>.</span>PopulateDataOnNotification<span style=color:#f92672>(</span>AvailabilityCheckNotification,ItemNo,UnitOfMeasureCode,InventoryQty,GrossReq,ReservedReq,SchedRcpt,ReservedRcpt,CurrentQuantity,CurrentReservedQty,TotalQuantity,EarliestAvailDate<span style=color:#f92672>)</span>;
|
||||
AvailabilityCheckNotification<span style=color:#f92672>.</span>SEND;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>Now, notifications do not replace each other, but we cannot recall them because we do not track each notification ID.</p>
|
||||
<p><a href=0677.3-notifications-smaller.PNG><img src=0677.3-notifications-smaller.PNG alt=" "></a></p>
|
||||
<p><em>Figure 3: Three sales lines with a notification for each one</em></p>
|
||||
<p>Imagine that you’re adding several items to a sales order, and inventory is low for some of the items. Each sales line will send a notification for its item if the quantity to sell is higher than the available inventory. By using dynamically generated notification IDs (<strong>CREATEGUID</strong>), each notification will not be overwritten, which is what we want. This is shown in Figure 3. But after you see the notification, you may decide to decrease the quantity in the sales line. At that point, the notification should be recalled. To do that, we need a way to track the notifications and their IDs.</p>
|
||||
|
|
@ -344,8 +345,6 @@ END;
|
|||
</li>
|
||||
<li>
|
||||
<p><strong>RecallNotificationsForRecord</strong>(RecId : RecordID;HandleDelayedInsert : Boolean)</p>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<li>Recalls all notifications that were sent by a given record ID. The HandleDelayedInsert flag should be TRUE if it is possible that the record ID provided is from a record that was not yet in the database (TRUE unless we recall notifications after deletion of a record).</li>
|
||||
</ul>
|
||||
|
|
@ -382,7 +381,6 @@ END;
|
|||
<p><em>Figure 4: without additional context</em></p>
|
||||
<p><a href=sequence2.png><img src=sequence2.png alt=" "></a></p>
|
||||
<p><em>Figure 5: with additional context</em></p>
|
||||
<p>__</p>
|
||||
<p>However, delayed insert means that the simple case seen above doesn’t happen very often. The issue is that when we call <strong>SendNotification</strong>, we provide the cause object’s record ID. If this object has not been inserted yet, which is often the case when the user creates a new invoice, a new line, and so on, the record ID is incomplete. When the object is inserted the record ID is completed, but if we call <strong>RecallNotificationsForRecord</strong> at a later point, the record ID will be different from the incomplete record ID we used when sending the notification. The solution is to detect that the object is not yet inserted when we send the notification, and at a later point, set the record ID when the cause object is inserted. </p>
|
||||
<p> </p>
|
||||
<p>The realistic case is:</p>
|
||||
|
|
@ -402,8 +400,8 @@ END;
|
|||
<p>COD312 (Cust-Check Cr. Limit)</p>
|
||||
<p>COD1508 (Notification Lifecycle Handler)</p>
|
||||
<p><strong>Related Patterns:</strong></p>
|
||||
<p><a href=/nav/w/designpatterns/284.using-in-context-notifications>In-context notifications</a> (<a href=https://community.dynamics.com/nav/w/designpatterns/284.using-in-context-notifications>https://community.dynamics.com/nav/w/designpatterns/284.using-in-context-notifications</a>)</p>
|
||||
<p><a href=/nav/w/designpatterns/283.singleton-codeunit>Singleton codeunit</a> (<a href=https://community.dynamics.com/nav/w/designpatterns/283.singleton-codeunit>https://community.dynamics.com/nav/w/designpatterns/283.singleton-codeunit</a>)</p>
|
||||
<p><a href=/navpatterns/1-patterns/notifications/in-context-notifications/>In-context notifications</a></p>
|
||||
<p><a href=/navpatterns/1-patterns/singleton/singleton-codeunit/>Singleton codeunit</a></p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -416,12 +414,12 @@ END;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Observer :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/observer/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -268,8 +268,7 @@ ALGuidelines.Dev
|
|||
</div>
|
||||
<main id=body-inner>
|
||||
<h1>Observer</h1>
|
||||
<p><em>By Nikolai L’Estrange, from TVision Technology Ltd. in the UK</em>
|
||||
_</p>
|
||||
<p><em>By Nikolai L’Estrange, from TVision Technology Ltd. in the UK</em></p>
|
||||
<h3 id=abstract>Abstract</h3>
|
||||
<p>Track all record changes against a defined table or set of tables.</p>
|
||||
<h3 id=problem>Problem</h3>
|
||||
|
|
@ -278,39 +277,67 @@ _</p>
|
|||
<p>Create a setup table to define which other tables you want to track changes for, and optionally what triggers you want to fire, then link this up to the standard triggers in Codeunit 1.</p>
|
||||
<p>Codeunit 1 Application Management contains the triggers OnDatabaseInsert, OnDatabaseModify, OnDatabaseDelete and OnDatabaseRename which are what we need to subscribe to in order to track record changes. However these triggers are only fired sometimes. This is determined by the parameters set in the function GetTableTriggerSetup, which is called once per table per session.</p>
|
||||
<p>In order to define which tables we are interested in we can create a new table with the following fields:</p>
|
||||
<pre><code>**Observable Table:**
|
||||
"Table ID" Integer Object.ID WHERE (Type=CONST(Table))
|
||||
TrackInsert Boolean \[optional\]
|
||||
TrackModify Boolean \[optional\]
|
||||
TrackDelete Boolean \[optional\]
|
||||
TrackRename Boolean \[optional\]
|
||||
</code></pre>
|
||||
<p><strong>Observable Table:</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>“Table ID”</th>
|
||||
<th>Integer</th>
|
||||
<th>Object.ID WHERE (Type=CONST(Table))</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>TrackInsert</td>
|
||||
<td>Boolean</td>
|
||||
<td>[optional]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TrackModify</td>
|
||||
<td>Boolean</td>
|
||||
<td>[optional]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TrackDelete</td>
|
||||
<td>Boolean</td>
|
||||
<td>[optional]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TrackRename</td>
|
||||
<td>Boolean</td>
|
||||
<td>[optional]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Then we can create a Codeunit that will set the Table Trigger Setup parameters and also subscribe to the OnDatabase triggers.</p>
|
||||
<pre><code>**LOCAL \[EventSubscriber\] GetTableTriggerSetup(TableId : Integer;VAR OnDatabaseInsert : Boolean;VAR OnDatabaseModify : Boolean;VAR OnDatabaseDelete : Boolean;VAR OnDatabaseRename : Boolean)**
|
||||
IF Observable.GET(TableId) THEN BEGIN
|
||||
IF Observable.TrackInsert THEN
|
||||
OnDatabaseInsert := TRUE;
|
||||
IF Observable.TrackModify THEN
|
||||
OnDatabaseModify := TRUE;
|
||||
IF Observable.TrackDelete THEN
|
||||
OnDatabaseDelete := TRUE;
|
||||
IF Observable.TrackRename THEN
|
||||
OnDatabaseRename := TRUE;
|
||||
END;
|
||||
**LOCAL \[EventSubscriber\] OnDatabaseInsert(RecRef : RecordRef)**
|
||||
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackInsert THEN
|
||||
//do something
|
||||
**LOCAL \[EventSubscriber\] OnDatabaseModify(RecRef : RecordRef)**
|
||||
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackModify THEN
|
||||
//do something
|
||||
**LOCAL \[EventSubscriber\] OnDatabaseDelete(RecRef : RecordRef)**
|
||||
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackDelete THEN
|
||||
//do something
|
||||
**LOCAL \[EventSubscriber\] OnDatabaseRename(RecRef : RecordRef;xRecRef : RecordRef)**
|
||||
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackRename THEN
|
||||
//do something
|
||||
</code></pre>
|
||||
<p><em><strong>Note:</strong></em> In NAV2016 all these functions can be EventSubscribers that subscribe to the functions in Codeunit 1 as per above, in earlier versions of NAV these functions will need to be Global and called explicitly from within the Codeunit 1 functions.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>LOCAL</span> [EventSubscriber] GetTableTriggerSetup<span style=color:#f92672>(</span>TableId : <span style=color:#66d9ef>Integer</span>;<span style=color:#66d9ef>VAR</span> OnDatabaseInsert : <span style=color:#66d9ef>Boolean</span>;<span style=color:#66d9ef>VAR</span> OnDatabaseModify : <span style=color:#66d9ef>Boolean</span>;<span style=color:#66d9ef>VAR</span> OnDatabaseDelete : <span style=color:#66d9ef>Boolean</span>;<span style=color:#66d9ef>VAR</span> OnDatabaseRename : <span style=color:#66d9ef>Boolean</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>TableId<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>TrackInsert <span style=color:#66d9ef>THEN</span>
|
||||
OnDatabaseInsert <span style=color:#f92672>:=</span> TRUE;
|
||||
<span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>TrackModify <span style=color:#66d9ef>THEN</span>
|
||||
OnDatabaseModify <span style=color:#f92672>:=</span> TRUE;
|
||||
<span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>TrackDelete <span style=color:#66d9ef>THEN</span>
|
||||
OnDatabaseDelete <span style=color:#f92672>:=</span> TRUE;
|
||||
<span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>TrackRename <span style=color:#66d9ef>THEN</span>
|
||||
OnDatabaseRename <span style=color:#f92672>:=</span> TRUE;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> [EventSubscriber] OnDatabaseInsert<span style=color:#f92672>(</span>RecRef : <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecRef<span style=color:#f92672>.</span>NUMBER<span style=color:#f92672>) </span><span style=color:#f92672>AND</span> Observable<span style=color:#f92672>.</span>TrackInsert <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#75715e>//do something
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#66d9ef>LOCAL</span> [EventSubscriber] OnDatabaseModify<span style=color:#f92672>(</span>RecRef : <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecRef<span style=color:#f92672>.</span>NUMBER<span style=color:#f92672>) </span><span style=color:#f92672>AND</span> Observable<span style=color:#f92672>.</span>TrackModify <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#75715e>//do something
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#66d9ef>LOCAL</span> [EventSubscriber] OnDatabaseDelete<span style=color:#f92672>(</span>RecRef : <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecRef<span style=color:#f92672>.</span>NUMBER<span style=color:#f92672>) </span><span style=color:#f92672>AND</span> Observable<span style=color:#f92672>.</span>TrackDelete <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#75715e>//do something
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#66d9ef>LOCAL</span> [EventSubscriber] OnDatabaseRename<span style=color:#f92672>(</span>RecRef : <span style=color:#66d9ef>RecordRef</span>;xRecRef : <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> Observable<span style=color:#f92672>.</span>Get<span style=color:#f92672>(</span>RecRef<span style=color:#f92672>.</span>NUMBER<span style=color:#f92672>) </span><span style=color:#f92672>AND</span> Observable<span style=color:#f92672>.</span>TrackRename <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#75715e>//do something
|
||||
</span></code></pre></div><p><em><strong>Note:</strong></em> In NAV2016 all these functions can be EventSubscribers that subscribe to the functions in Codeunit 1 as per above, in earlier versions of NAV these functions will need to be Global and called explicitly from within the Codeunit 1 functions.</p>
|
||||
<h3 id=nav-usages>NAV Usages</h3>
|
||||
<p>Variations of this pattern exists in the standard product in:</p>
|
||||
<ul>
|
||||
|
|
@ -339,12 +366,12 @@ IF Observable.Get(RecRef.NUMBER) AND Observable.TrackRename THEN
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Posting Routine - Select Behavior :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/posting-routine-select-behavior/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -283,12 +283,12 @@ ALGuidelines.Dev
|
|||
<p>Or in case of the Post&Print, the selection codeunit is different:</p>
|
||||
<p><a href=6170.PostingRoutineSelectBehaviour4.png><img src=6170.PostingRoutineSelectBehaviour4.png alt=" "></a></p>
|
||||
<p>Next, the user is able to select the options with an STRMENU, which results in filling in the fields above, like:</p>
|
||||
<p>Selection := STRMENU(Text000,3);<br>
|
||||
IF Selection = 0 THEN<br>
|
||||
EXIT;<br>
|
||||
Ship := Selection IN [1,3];<br>
|
||||
Invoice := Selection IN [2,3];</p>
|
||||
<p>The processing codeunit is being called after these options were set.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>Selection <span style=color:#f92672>:=</span> STRMENU<span style=color:#f92672>(</span>Text000,<span style=color:#ae81ff>3</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> Selection = <span style=color:#ae81ff>0</span> <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>EXIT</span>;
|
||||
Ship <span style=color:#f92672>:=</span> Selection <span style=color:#66d9ef>IN</span> [<span style=color:#ae81ff>1</span>,<span style=color:#ae81ff>3</span>];
|
||||
Invoice <span style=color:#f92672>:=</span> Selection <span style=color:#66d9ef>IN</span> [<span style=color:#ae81ff>2</span>,<span style=color:#ae81ff>3</span>];
|
||||
</code></pre></div><p>The processing codeunit is being called after these options were set.</p>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>This is also being used in the Purchase Post.</p>
|
||||
<p>However, the Service Post works different. In Short:</p>
|
||||
|
|
@ -317,12 +317,12 @@ Invoice := Selection IN [2,3];</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Product Name :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/product-name/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -297,12 +297,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/queries/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Queries :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/queries/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -268,12 +268,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
Abstract This pattern explains how to perform SELECT DISTINCT by using queries in Dynamics NAV.
|
||||
Description
|
||||
When working with tables, sometimes a developer needs to perform a SELECT DISTINCT (also known as SELECT UNIQUE) from a table. As NAV does not provide this out of the box, we present below a way to select unique records by using queries.
|
||||
Problem statement</description></item><item><title>Use Queries to Detect Duplicate Records</title><link>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-detect-duplicate-records/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-detect-duplicate-records/</guid><description>Originally by Abshishek Ghosh and Bogdan Sturzoiu at Microsoft Development Center Copenhagen
|
||||
Problem statement
|
||||
Let&rsquo;s consider the VAT Entry table as below:</description></item><item><title>Use Queries to Detect Duplicate Records</title><link>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-detect-duplicate-records/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-detect-duplicate-records/</guid><description>Originally by Abshishek Ghosh and Bogdan Sturzoiu at Microsoft Development Center Copenhagen
|
||||
Abstract This pattern uses queries to create an efficient way to detect duplicate entries in a table. This is, for example, useful when trying to find out which customers or contacts have the same names, so we can merge them later.
|
||||
Description Duplicate detection has several requirements in Microsoft Dynamics NAV. One method to eliminate duplication is by defining the relevant field as the primary key.</description></item><item><title>Use Queries to Replace Nested Loops</title><link>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-replace-nested-loops/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/queries/use-queries-to-replace-nested-loops/</guid><description>Originally by Bogdan Sturzoiu, Microsoft Development Center Copenhagen
|
||||
Abstract This pattern shows how the new query object type introduced in NAV 2013 allows you to replace costly loops when inspecting data from two or more tables.
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>SELECT DISTINCT with Queries :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/queries/select-distinct-with-queries/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -251,8 +251,8 @@ ALGuidelines.Dev
|
|||
<ul>
|
||||
<li>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#example><strong>Example</strong></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#example>Example</a></li>
|
||||
<li><a href=#nav-usages><strong>NAV Usages</strong></a></li>
|
||||
<li><a href=#related-topics><strong>Related Topics</strong></a></li>
|
||||
</ul>
|
||||
|
|
@ -267,18 +267,15 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>SELECT DISTINCT with Queries</h1>
|
||||
<p><em>By Bogdana Botez, at Microsoft Development Center Copenhagen</em></p>
|
||||
<h3 id=abstract><strong>Abstract</strong></h3>
|
||||
<h3 id=abstract>Abstract</h3>
|
||||
<p>This pattern explains how to perform SELECT DISTINCT by using queries in Dynamics NAV.</p>
|
||||
<hr>
|
||||
<p><strong>Description</strong></p>
|
||||
<p>When working with tables, sometimes a developer needs to perform a SELECT DISTINCT (also known as SELECT UNIQUE) from a table. As NAV does not provide this out of the box, we present below a way to select unique records by using queries.</p>
|
||||
<hr>
|
||||
<p><strong>Problem statement</strong></p>
|
||||
<p>Let’s consider the <strong>VAT Entry</strong> table as below: <a href=https://microsoft.sharepoint.com/teams/DynamicsNAV/Wiki/Nav%20Wiki%20Documents/NAV%20App%20Patterns/NAV%20App%20Patterns%20for%20Review/Table%20Select%20Distinct.docx#_msocom_1><br>
|
||||
</a></p>
|
||||
<p>Let’s consider the <strong>VAT Entry</strong> table as below: <a href=https://microsoft.sharepoint.com/teams/DynamicsNAV/Wiki/Nav%20Wiki%20Documents/NAV%20App%20Patterns/NAV%20App%20Patterns%20for%20Review/Table%20Select%20Distinct.docx#_msocom_1> </a></p>
|
||||
<p><a href=6521.clip_5F00_image001.png><img src=6521.clip_5F00_image001.png alt=" "></a></p>
|
||||
<p>The goal is to select one line for each separate document that produced VAT Entries. In other words, we want records grouped by <strong>Type, Document Type</strong> and <strong>Document No.</strong>. However, if there are multiple lines with the same value of the triad <strong>Type, Document Type</strong> and <strong>Document No.</strong> in the <strong>VAT Entry</strong> table, we only want to see one of them.</p>
|
||||
<h4 id=solution><strong>Solution</strong></h4>
|
||||
<h4 id=solution>Solution</h4>
|
||||
<p>Create a new query object <strong>VAT Entry Distinct Document No.</strong>, with a single DataItem sourced from <strong>VAT Entry</strong> table. Add the three desired group-by fields <strong>Type, Document Type</strong> and <strong>Document No.</strong> as columns.</p>
|
||||
<p><a href=clip_5F00_image002.png><img src=clip_5F00_image002.png alt=" "></a></p>
|
||||
<p>To enable grouping, add one more column, with <strong>Method Type</strong> = <strong>Totals</strong>. This will automatically set the <strong>Group By</strong> checkbox to TRUE on the three precedent fields.</p>
|
||||
|
|
@ -286,7 +283,7 @@ ALGuidelines.Dev
|
|||
<p><a href=clip_5F00_image003.png><img src=clip_5F00_image003.png alt=" "></a></p>
|
||||
<p>Running the query yields a single record per document. You can notice in the second line below for example, how the sales invoice number 103001 had 2 VAT Entries, but it shows up only once in the query:</p>
|
||||
<p><a href=clip_5F00_image004.png><img src=clip_5F00_image004.png alt=" "></a></p>
|
||||
<h3 id=example><strong>Example</strong></h3>
|
||||
<h3 id=example>Example</h3>
|
||||
<p>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 <strong>Method Type</strong> = <strong>None</strong> will indeed show more information, but it <em>might</em> affect the grouping. More details below.</p>
|
||||
<p><strong>The grouping is affected</strong> for example when the additional column is the <strong>VAT Entry No</strong>. In this case, this column brings up additional grouping criteria and one group for each entry number will end up being created.</p>
|
||||
<p><a href=clip_5F00_image005.png><img src=clip_5F00_image005.png alt=" "></a></p>
|
||||
|
|
@ -315,12 +312,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Use Queries to Detect Duplicate Records :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/queries/use-queries-to-detect-duplicate-records/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -249,13 +249,9 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a>
|
||||
<ul>
|
||||
<li></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href=#usage><strong>Usage</strong></a>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a>
|
||||
<ul>
|
||||
<li></li>
|
||||
</ul>
|
||||
|
|
@ -271,29 +267,27 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Use Queries to Detect Duplicate Records</h1>
|
||||
<p><em>Originally by Abshishek Ghosh and Bogdan Sturzoiu at Microsoft Development Center Copenhagen</em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>This pattern uses queries to create an efficient way to detect duplicate entries in a table. This is, for example, useful when trying to find out which customers or contacts have the same names, so we can merge them later.</p>
|
||||
<h2 id=description><strong>Description</strong></h2>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>Duplicate detection has several requirements in Microsoft Dynamics NAV. One method to eliminate duplication is by defining the relevant field as the primary key. However, this method is not always practical either due to the size of the field or due to business requirements that dictate how duplicates are detected but not necessarily how they are eliminated. An example of this method is to detect contacts with the same name and take action to merge them if they are.</p>
|
||||
<p>Before Dynamics NAV 2013, the only possibility was to iterate through the table in a loop and then create a sub-loop where another instance of the same table is filtered to check for duplicates. For example, to check for duplicate names in the Customer table, the code would look like this:</p>
|
||||
<pre><code>PROCEDURE HasDuplicateCustomers@26() : Boolean;
|
||||
VAR
|
||||
Customer@1000 : Record 18;
|
||||
Customer2@1001 : Record 18;
|
||||
BEGIN
|
||||
IF Customer.FINDSET THEN
|
||||
REPEAT
|
||||
Customer2.SETRANGE(Name,Customer.Name);
|
||||
IF Customer2.COUNT \> 1 THEN
|
||||
EXIT(TRUE);
|
||||
UNTIL Customer.NEXT = 0;
|
||||
EXIT(FALSE);
|
||||
END;
|
||||
</code></pre>
|
||||
<h4 id=heading></h4>
|
||||
<p>This code would involve setting filters on the <strong>Customer</strong> table as many times as there are records in the table. This is an expensive operation.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> HasDuplicateCustomers@<span style=color:#ae81ff>26</span><span style=color:#f92672>() </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
Customer@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>18</span>;
|
||||
Customer2@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>18</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> Customer<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
Customer2<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Name,Customer<span style=color:#f92672>.</span>Name<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> Customer2<span style=color:#f92672>.</span><span style=color:#66d9ef>COUNT</span> \> <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>TRUE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> Customer<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>This code would involve setting filters on the <strong>Customer</strong> table as many times as there are records in the table. This is an expensive operation.</p>
|
||||
<p>Starting with Dynamics NAV 2013, we can use queries to create a more efficient implementation of the same logic.</p>
|
||||
<h2 id=usage><strong>Usage</strong></h2>
|
||||
<h2 id=usage>Usage</h2>
|
||||
<p>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.</p>
|
||||
<p><strong>Step 1</strong> – <strong>Creating the Query</strong></p>
|
||||
<ul>
|
||||
|
|
@ -303,7 +297,7 @@ END;
|
|||
</ul>
|
||||
<p>Continuing with our Customer Name example, here is how the query would look:</p>
|
||||
<p><a href=clip_5F00_image002.jpg><img src=clip_5F00_image002.jpg alt=" "></a></p>
|
||||
<h4 id=heading-1></h4>
|
||||
<h4 id=heading></h4>
|
||||
<pre><code>ELEMENTS
|
||||
{
|
||||
{ 1 ; ;DataItem; ;
|
||||
|
|
@ -311,26 +305,22 @@ DataItemTable=Table18 }
|
|||
{ 2 ;1 ;Column ; ;
|
||||
DataSource=Name }
|
||||
{ 3 ;1 ;Column ; ;
|
||||
ColumnFilter=Count\_=FILTER(\>1);
|
||||
ColumnFilter=Count_=FILTER(\>1);
|
||||
MethodType=Totals;
|
||||
Method=Count }
|
||||
}
|
||||
</code></pre>
|
||||
<p>**<br>
|
||||
**</p>
|
||||
<p><strong>Step 2 – Invoking the Query to Check for Duplicates</strong></p>
|
||||
<p>Now that the query is created, all we need to do is to invoke the query and check if any records are returned, which would mean that there are duplicates.</p>
|
||||
<p>Here is an alternate implementation of the <strong>HasDuplicateCustomers</strong> method using the query that we created:</p>
|
||||
<pre><code>PROCEDURE HasDuplicateCustomersWithQuery@27() : Boolean;
|
||||
VAR
|
||||
CustomerDuplicate@1000 : Query 70000;
|
||||
BEGIN
|
||||
CustomerDuplicate.OPEN;
|
||||
EXIT(CustomerDuplicate.READ);
|
||||
END;
|
||||
</code></pre>
|
||||
<h4 id=heading-2></h4>
|
||||
<p><strong>Examples</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> HasDuplicateCustomersWithQuery@<span style=color:#ae81ff>27</span><span style=color:#f92672>() </span>: <span style=color:#66d9ef>Boolean</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
CustomerDuplicate@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Query</span> <span style=color:#ae81ff>70000</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
CustomerDuplicate<span style=color:#f92672>.</span>OPEN;
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>CustomerDuplicate<span style=color:#f92672>.</span>READ<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><strong>Examples</strong></p>
|
||||
<ul>
|
||||
<li><strong>Acc. Sched. Chart Management</strong> codeunit (762),<br>
|
||||
methods CheckDuplicateAccScheduleLineDescription and CheckDuplicateColumnLayoutColumnHeader</li>
|
||||
|
|
@ -351,12 +341,12 @@ methods CheckDuplicateAnalysisLineDescription and CheckDuplicateAnalysisColumnHe
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Use Queries to Replace Nested Loops :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/queries/use-queries-to-replace-nested-loops/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -249,12 +249,12 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a>
|
||||
<li><a href=#abstract>Abstract</a>
|
||||
<ul>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#usage><strong>Usage</strong></a></li>
|
||||
<li><a href=#nav-specific-examples><strong>NAV Specific Examples</strong></a></li>
|
||||
<li><a href=#ideas-for-improvement><strong>Ideas for Improvement</strong></a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a></li>
|
||||
<li><a href=#nav-specific-examples>NAV Specific Examples</a></li>
|
||||
<li><a href=#ideas-for-improvement>Ideas for Improvement</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -267,18 +267,18 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Use Queries to Replace Nested Loops</h1>
|
||||
<p><em>Originally by Bogdan Sturzoiu, Microsoft Development Center Copenhagen</em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>This pattern shows how the new query object type introduced in NAV 2013 allows you to replace costly loops when inspecting data from two or more tables.</p>
|
||||
<h3 id=description><strong>Description</strong></h3>
|
||||
<h3 id=description>Description</h3>
|
||||
<p>One of the core operations in a relational database is joining two or more tables. For example, you might need to extract all sales lines in the database together with information regarding the related sales header. This requires joining the Sales Header and Sales Line tables using Sales Header No. as the connecting field.;</p>
|
||||
<p>The join operation has traditionally been done in C/AL by record looping. When NAV 2013 introduced the query object, it allowed us to produce a data set that is the result of a join operation between two or more tables. This simplifies the problem of finding related records in two tables linked through a foreign key.</p>
|
||||
<h4 id=pattern-elements><strong>Pattern Elements</strong></h4>
|
||||
<h4 id=pattern-elements>Pattern Elements</h4>
|
||||
<ol>
|
||||
<li>Two or more tables that contain records linked through a foreign key: Table 1, Table 2, Table n.</li>
|
||||
<li>A query object Query X, that joins Table 1, Table 2, etc. based on the connecting key.</li>
|
||||
<li>A processing codeunit that loops through the query records (or any other code-bearing object).</li>
|
||||
</ol>
|
||||
<h4 id=pattern-steps><strong>Pattern Steps</strong></h4>
|
||||
<h4 id=pattern-steps>Pattern Steps</h4>
|
||||
<ol>
|
||||
<li>Run the query on the connected tables.</li>
|
||||
<li>Loop through the records returned by the query.</li>
|
||||
|
|
@ -286,141 +286,128 @@ ALGuidelines.Dev
|
|||
</ol>
|
||||
<p><a href=5040.clip_5F00_image002.png><img src=5040.clip_5F00_image002.png alt=" "></a></p>
|
||||
<p><em>Figure 1. The pattern elements</em></p>
|
||||
<h3 id=usage><strong>Usage</strong></h3>
|
||||
<h4 id=sample-problem><strong>Sample Problem</strong></h4>
|
||||
<h3 id=usage>Usage</h3>
|
||||
<h4 id=sample-problem>Sample Problem</h4>
|
||||
<p>The Bank Acc. Reconciliation Line table (274) and the Bank Account Ledger Entry table (271) are connected through the Bank Account No. field. Identify the matching pairs of records based on having the same remaining amount and transaction date.</p>
|
||||
<h4 id=solution-using-nested-loops><strong>Solution Using Nested Loops</strong></h4>
|
||||
<h4 id=solution-using-nested-loops>Solution Using Nested Loops</h4>
|
||||
<p>The classic C/AL approach is to:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Set the necessary filters on the left table, i.e. table 274.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Loop through the filtered records.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For each record in the filter, find the related records in the right table (table 271) and set the required filters on it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For each pair of records from the left and right table, decide if they are a solution and if so, apply them to each other.</p>
|
||||
<p>PROCEDURE MatchSingle@5(BankAccReconciliation@1003 : Record 273);
|
||||
VAR
|
||||
BankAccRecLine@1005 : Record 274;
|
||||
BankAccLedgerEntry@1006 : Record 271;
|
||||
BankAccEntrySetReconNo@1007 : Codeunit 375;
|
||||
BEGIN
|
||||
BankAccRecLine.SETRANGE(“Bank Account No.",BankAccReconciliation.“Bank Account No.");
|
||||
BankAccRecLine.SETRANGE(“Statement No.",BankAccReconciliation.“Statement No.");
|
||||
BankAccRecLine.SETFILTER(Difference,'<>%1',0);
|
||||
BankAccRecLine.SETRANGE(Type,BankAccRecLine.Type::“Bank Account Ledger Entry”);
|
||||
IF BankAccRecLine.FINDSET THEN
|
||||
REPEAT
|
||||
BankAccLedgerEntry.SETRANGE(“Bank Account No.",BankAccRecLine.“Bank Account No.");
|
||||
BankAccLedgerEntry.SETRANGE(Open,TRUE);
|
||||
BankAccLedgerEntry.SETRANGE(“Statement Status”,BankAccLedgerEntry.“Statement Status”::Open);
|
||||
BankAccLedgerEntry.SETFILTER(“Remaining Amount”,'<>%1',0);
|
||||
IF BankAccLedgerEntry.FINDSET THEN
|
||||
REPEAT
|
||||
IF (BankAccRecLine.Difference = BankAccLedgerEntry.“Remaining Amount”) AND
|
||||
(BankAccRecLine.“Transaction Date” = BankAccLedgerEntry.“Posting Date”) THEN
|
||||
BankAccEntrySetReconNo.ApplyEntries(
|
||||
BankAccRecLine,BankAccLedgerEntry, Relation::“One-to-One”);
|
||||
UNTIL BankAccLedgerEntry.NEXT = 0;
|
||||
UNTIL BankAccRecLine.NEXT = 0;
|
||||
END;</p>
|
||||
</li>
|
||||
<li>Set the necessary filters on the left table, i.e. table 274.</li>
|
||||
<li>Loop through the filtered records.</li>
|
||||
<li>For each record in the filter, find the related records in the right table (table 271) and set the required filters on it.</li>
|
||||
<li>For each pair of records from the left and right table, decide if they are a solution and if so, apply them to each other.</li>
|
||||
</ol>
|
||||
<p><strong>Solution Using Query</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> MatchSingle@<span style=color:#ae81ff>5</span><span style=color:#f92672>(</span>BankAccReconciliation@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>273</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankAccRecLine@<span style=color:#ae81ff>1005</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>274</span>;
|
||||
BankAccLedgerEntry@<span style=color:#ae81ff>1006</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>271</span>;
|
||||
BankAccEntrySetReconNo@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>375</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
BankAccRecLine<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Bank Account No.",BankAccReconciliation<span style=color:#f92672>.</span>"Bank Account No."<span style=color:#f92672>)</span>;
|
||||
BankAccRecLine<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Statement No.",BankAccReconciliation<span style=color:#f92672>.</span>"Statement No."<span style=color:#f92672>)</span>;
|
||||
BankAccRecLine<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>Difference,<span style=color:#e6db74>'<>%1'</span>,<span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>;
|
||||
BankAccRecLine<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span><span style=color:#66d9ef>Type</span>,BankAccRecLine<span style=color:#f92672>.</span><span style=color:#66d9ef>Type</span>::"Bank Account Ledger Entry"<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> BankAccRecLine<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
BankAccLedgerEntry<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Bank Account No.",BankAccRecLine<span style=color:#f92672>.</span>"Bank Account No."<span style=color:#f92672>)</span>;
|
||||
BankAccLedgerEntry<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Open,TRUE<span style=color:#f92672>)</span>;
|
||||
BankAccLedgerEntry<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Statement Status",BankAccLedgerEntry<span style=color:#f92672>.</span>"Statement Status"::Open<span style=color:#f92672>)</span>;
|
||||
BankAccLedgerEntry<span style=color:#f92672>.</span>SETFILTER<span style=color:#f92672>(</span>"Remaining Amount",<span style=color:#e6db74>'<>%1'</span>,<span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>IF</span> BankAccLedgerEntry<span style=color:#f92672>.</span>FINDSET <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>REPEAT</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>(</span>BankAccRecLine<span style=color:#f92672>.</span>Difference = BankAccLedgerEntry<span style=color:#f92672>.</span>"Remaining Amount"<span style=color:#f92672>) </span><span style=color:#f92672>AND</span>
|
||||
<span style=color:#f92672>(</span>BankAccRecLine<span style=color:#f92672>.</span>"Transaction Date" = BankAccLedgerEntry<span style=color:#f92672>.</span>"Posting Date"<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
BankAccEntrySetReconNo<span style=color:#f92672>.</span>ApplyEntries<span style=color:#f92672>(
|
||||
</span><span style=color:#f92672> </span>BankAccRecLine,BankAccLedgerEntry, Relation::"One-to-One"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> BankAccLedgerEntry<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>UNTIL</span> BankAccRecLine<span style=color:#f92672>.</span>NEXT = <span style=color:#ae81ff>0</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><strong>Solution Using Query</strong></p>
|
||||
<p>The new query-based approach involves:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Define a query that returns the full filtered join of tables 271 and 274.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Loop through the records returned by the query.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For each query record, decide if it represents a solution and then connect the two table records that formed it through an application.</p>
|
||||
<p>PROCEDURE MatchSingle@5(BankAccReconciliation@1003 : Record 273);
|
||||
VAR
|
||||
BankRecMatchCandidates@1001 : Query 1252;
|
||||
BankAccEntrySetReconNo@1007 : Codeunit 375;
|
||||
BEGIN
|
||||
BankRecMatchCandidates.SETRANGE(Rec_Line_Bank_Account_No,
|
||||
BankAccReconciliation.“Bank Account No.");
|
||||
BankRecMatchCandidates.SETRANGE(Rec_Line_Statement_No,
|
||||
BankAccReconciliation.“Statement No.");
|
||||
IF NOT BankRecMatchCandidates.OPEN THEN
|
||||
EXIT;
|
||||
WHILE BankRecMatchCandidates.READ DO BEGIN
|
||||
BankAccLedgerEntry.GET(BankRecMatchCandidates.Entry_No);
|
||||
BankAccRecLine.GET(BankAccRecLine.“Statement Type”::“Bank Reconciliation”,
|
||||
BankRecMatchCandidates.Rec_Line_Bank_Account_No,
|
||||
BankRecMatchCandidates.Rec_Line_Statement_No,
|
||||
BankRecMatchCandidates.Rec_Line_Statement_Line_No);
|
||||
BankAccEntrySetReconNo.ApplyEntries(BankAccRecLine,BankAccLedgerEntry,
|
||||
Relation::“One-to-One”);
|
||||
END;
|
||||
END;</p>
|
||||
</li>
|
||||
<li>Define a query that returns the full filtered join of tables 271 and 274.</li>
|
||||
<li>Loop through the records returned by the query.</li>
|
||||
<li>For each query record, decide if it represents a solution and then connect the two table records that formed it through an application.</li>
|
||||
</ol>
|
||||
<p>where the query 1252 is defined as:</p>
|
||||
<pre><code>OBJECT Query 1252 Bank Rec. Match Candidates
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> MatchSingle@<span style=color:#ae81ff>5</span><span style=color:#f92672>(</span>BankAccReconciliation@<span style=color:#ae81ff>1003</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>273</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
BankRecMatchCandidates@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Query</span> <span style=color:#ae81ff>1252</span>;
|
||||
BankAccEntrySetReconNo@<span style=color:#ae81ff>1007</span> : <span style=color:#66d9ef>Codeunit</span> <span style=color:#ae81ff>375</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
BankRecMatchCandidates<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Rec_Line_Bank_Account_No,
|
||||
BankAccReconciliation<span style=color:#f92672>.</span>"Bank Account No."<span style=color:#f92672>)</span>;
|
||||
BankRecMatchCandidates<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Rec_Line_Statement_No,
|
||||
BankAccReconciliation<span style=color:#f92672>.</span>"Statement No."<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> BankRecMatchCandidates<span style=color:#f92672>.</span>OPEN <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>EXIT</span>;
|
||||
|
||||
<span style=color:#66d9ef>WHILE</span> BankRecMatchCandidates<span style=color:#f92672>.</span>READ <span style=color:#66d9ef>DO</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
BankAccLedgerEntry<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>BankRecMatchCandidates<span style=color:#f92672>.</span>Entry_No<span style=color:#f92672>)</span>;
|
||||
BankAccRecLine<span style=color:#f92672>.</span>GET<span style=color:#f92672>(</span>BankAccRecLine<span style=color:#f92672>.</span>"Statement Type"::"Bank Reconciliation",
|
||||
BankRecMatchCandidates<span style=color:#f92672>.</span>Rec_Line_Bank_Account_No,
|
||||
BankRecMatchCandidates<span style=color:#f92672>.</span>Rec_Line_Statement_No,
|
||||
BankRecMatchCandidates<span style=color:#f92672>.</span>Rec_Line_Statement_Line_No<span style=color:#f92672>)</span>;
|
||||
BankAccEntrySetReconNo<span style=color:#f92672>.</span>ApplyEntries<span style=color:#f92672>(</span>BankAccRecLine,BankAccLedgerEntry,
|
||||
Relation::"One-to-One"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>where the query 1252 is defined as:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OBJECT <span style=color:#66d9ef>Query</span> <span style=color:#ae81ff>1252</span> Bank Rec<span style=color:#f92672>. </span>Match Candidates
|
||||
{
|
||||
OBJECT-PROPERTIES
|
||||
{
|
||||
Date=;
|
||||
Time=;
|
||||
Version List=;
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
}
|
||||
ELEMENTS
|
||||
{
|
||||
{ 1 ; ;DataItem; ;
|
||||
DataItemTable=Table274;
|
||||
DataItemTableFilter=Difference=FILTER(<\>0),
|
||||
Type=FILTER(=Bank Account Ledger Entry) }
|
||||
{ 2 ;1 ;Column ;Rec\_Line\_Bank\_Account\_No;
|
||||
DataSource=Bank Account No. }
|
||||
{ 3 ;1 ;Column ;Rec\_Line\_Statement\_No;
|
||||
DataSource=Statement No. }
|
||||
{ 4 ;1 ;Column ;Rec\_Line\_Statement\_Line\_No;
|
||||
DataSource=Statement Line No. }
|
||||
{ 5 ;1 ;Column ;Rec\_Line\_Transaction\_Date;
|
||||
DataSource=Transaction Date }
|
||||
{ 6 ;1 ;Column ;Rec\_Line\_Difference ;
|
||||
DataSource=Difference }
|
||||
{ 7 ;1 ;DataItem; ;
|
||||
DataItemTable=Table271;
|
||||
DataItemTableFilter=Remaining Amount=FILTER(<\>0),
|
||||
Open=CONST(Yes),
|
||||
Statement Status=FILTER(Open);
|
||||
DataItemLink=Bank Account No.=Bank\_Acc\_Reconciliation\_Line."Bank Account o.",
|
||||
Remaining Amount=Bank\_Acc\_Reconciliation\_Line.Difference,
|
||||
Posting Date=Bank\_Acc\_Reconciliation\_Line."Transaction Date" }
|
||||
{ 8 ;2 ;Column ; ;
|
||||
DataSource=Entry No. }
|
||||
{ 9 ;2 ;Column ;Bank\_Account\_No ;
|
||||
DataSource=Bank Account No. }
|
||||
{ 10 ;2 ;Column ; ;
|
||||
DataSource=Posting Date }
|
||||
{ 11 ;2 ;Column ; ;
|
||||
DataSource=Remaining Amount }
|
||||
{ 12 ;2 ;Column ;Bank\_Ledger\_Entry\_Open;
|
||||
DataSource=Open }
|
||||
{ 13 ;2 ;Column ; ;
|
||||
DataSource=Statement Status }
|
||||
}
|
||||
CODE
|
||||
{
|
||||
BEGIN
|
||||
END.
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id=heading></h4>
|
||||
<p>When comparing the two implementations, we notice the following advantages of using a query instead of two loops:Comparison</p>
|
||||
OBJECT<span style=color:#f92672>-</span>PROPERTIES
|
||||
{
|
||||
<span style=color:#66d9ef>Date</span>=;
|
||||
<span style=color:#66d9ef>Time</span>=;
|
||||
<span style=color:#66d9ef>Version</span> <span style=color:#66d9ef>List</span>=;
|
||||
}
|
||||
PROPERTIES
|
||||
{
|
||||
}
|
||||
<span style=color:#66d9ef>ELEMENTS</span>
|
||||
{
|
||||
{ <span style=color:#ae81ff>1</span> ; ;<span style=color:#66d9ef>DataItem</span>; ;
|
||||
DataItemTable=Table274;
|
||||
DataItemTableFilter=Difference=<span style=color:#66d9ef>FILTER</span><span style=color:#f92672>(</span><><span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>,
|
||||
<span style=color:#66d9ef>Type</span>=<span style=color:#66d9ef>FILTER</span><span style=color:#f92672>(</span>=Bank Account Ledger Entry<span style=color:#f92672>) </span>}
|
||||
{ <span style=color:#ae81ff>2</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>Column</span> ;Rec_Line_Bank_Account_No;
|
||||
DataSource=Bank Account No<span style=color:#f92672>. </span>}
|
||||
{ <span style=color:#ae81ff>3</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>Column</span> ;Rec_Line_Statement_No;
|
||||
DataSource=Statement No<span style=color:#f92672>. </span>}
|
||||
{ <span style=color:#ae81ff>4</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>Column</span> ;Rec_Line_Statement_Line_No;
|
||||
DataSource=Statement Line No<span style=color:#f92672>. </span>}
|
||||
{ <span style=color:#ae81ff>5</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>Column</span> ;Rec_Line_Transaction_Date;
|
||||
DataSource=Transaction <span style=color:#66d9ef>Date</span> }
|
||||
{ <span style=color:#ae81ff>6</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>Column</span> ;Rec_Line_Difference ;
|
||||
DataSource=Difference }
|
||||
{ <span style=color:#ae81ff>7</span> ;<span style=color:#ae81ff>1</span> ;<span style=color:#66d9ef>DataItem</span>; ;
|
||||
DataItemTable=Table271;
|
||||
DataItemTableFilter=Remaining Amount=<span style=color:#66d9ef>FILTER</span><span style=color:#f92672>(</span><><span style=color:#ae81ff>0</span><span style=color:#f92672>)</span>,
|
||||
Open=<span style=color:#66d9ef>CONST</span><span style=color:#f92672>(</span>Yes<span style=color:#f92672>)</span>,
|
||||
Statement Status=<span style=color:#66d9ef>FILTER</span><span style=color:#f92672>(</span>Open<span style=color:#f92672>)</span>;
|
||||
DataItemLink=Bank Account No<span style=color:#f92672>.</span>=Bank_Acc_Reconciliation_Line<span style=color:#f92672>.</span>"Bank Account o.",
|
||||
Remaining Amount=Bank_Acc_Reconciliation_Line<span style=color:#f92672>.</span>Difference,
|
||||
Posting <span style=color:#66d9ef>Date</span>=Bank_Acc_Reconciliation_Line<span style=color:#f92672>.</span>"Transaction Date" }
|
||||
{ <span style=color:#ae81ff>8</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ; ;
|
||||
DataSource=Entry No<span style=color:#f92672>. </span>}
|
||||
{ <span style=color:#ae81ff>9</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ;Bank_Account_No ;
|
||||
DataSource=Bank Account No<span style=color:#f92672>. </span>}
|
||||
{ <span style=color:#ae81ff>10</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ; ;
|
||||
DataSource=Posting <span style=color:#66d9ef>Date</span> }
|
||||
{ <span style=color:#ae81ff>11</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ; ;
|
||||
DataSource=Remaining Amount }
|
||||
{ <span style=color:#ae81ff>12</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ;Bank_Ledger_Entry_Open;
|
||||
DataSource=Open }
|
||||
{ <span style=color:#ae81ff>13</span> ;<span style=color:#ae81ff>2</span> ;<span style=color:#66d9ef>Column</span> ; ;
|
||||
DataSource=Statement Status }
|
||||
}
|
||||
<span style=color:#66d9ef>CODE</span>
|
||||
{
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>END</span><span style=color:#f92672>.
|
||||
</span><span style=color:#f92672> </span>}
|
||||
</code></pre></div><p>When comparing the two implementations, we notice the following advantages of using a query instead of two loops:Comparison</p>
|
||||
<ol>
|
||||
<li>A query produces the Cartesian product of tables 1 and 2 faster than by looping through both of them. The advantage grows as there are more tables linked.</li>
|
||||
</ol>
|
||||
|
|
@ -430,9 +417,9 @@ END.
|
|||
<li>Using a query only requires one loop, whereas joining two or more tables requires multiple code loops that quickly become difficult to read and follow.</li>
|
||||
<li>Queries are easy to create and maintain and generally provide a cleaner design.</li>
|
||||
</ol>
|
||||
<h3 id=nav-specific-examples><strong>NAV Specific Examples</strong></h3>
|
||||
<h3 id=nav-specific-examples>NAV Specific Examples</h3>
|
||||
<p>In Microsoft Dynamics NAV 2013 R2, we can see the query object used in the bank account reconciliation matching algorithm. The object is query Bank Rec. Match Candidates query (1252), and it is called by the matching engine in the Match Bank Rec. Lines codeunit (1252).</p>
|
||||
<h3 id=ideas-for-improvement><strong>Ideas for Improvement</strong></h3>
|
||||
<h3 id=ideas-for-improvement>Ideas for Improvement</h3>
|
||||
<p>The query object type could be improved to allow the passing of parameters at runtime, or, in general, being built dynamically at runtime. This will remove the need for multiple static definitions of the same base query used in slightly different contexts.</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
|
|
@ -446,12 +433,12 @@ END.
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Read-once Initialization and Validation :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/read-once-initialization-and-validation/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,13 +248,13 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#nav-specific-example><strong>NAV Specific Example</strong></a></li>
|
||||
<li><a href=#nav-usages><strong>NAV Usages</strong></a></li>
|
||||
<li><a href=#ideas-for-improvement><strong>Ideas for improvement</strong></a></li>
|
||||
<li><a href=#consequences><strong>Consequences</strong></a></li>
|
||||
<li><a href=#related-topics><strong>Related Topics</strong></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#nav-specific-example>NAV Specific Example</a></li>
|
||||
<li><a href=#nav-usages>NAV Usages</a></li>
|
||||
<li><a href=#ideas-for-improvement>Ideas for improvement</a></li>
|
||||
<li><a href=#consequences>Consequences</a></li>
|
||||
<li><a href=#related-topics>Related Topics</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -265,35 +265,32 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Read-once Initialization and Validation</h1>
|
||||
<p><em>By Tim Grant</em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>One time query and validation of a setup table.</p>
|
||||
<hr>
|
||||
<h2 id=description><strong>Description</strong></h2>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>Firstly identifies if a setup table record is in memory, removing the need to execute and validate the re-query again within a code unit. (From NAV 2013+ service tier database caching exists).</p>
|
||||
<p>If you need to query a setup table, but not sure if the table is yet in memory from earlier code, this helps to determine this call (see Singleton Table pattern).</p>
|
||||
<p>Allows a central function to validate critical fields before processing automated code. <strong>TESTFIELD</strong> calls are added to the function and not the INIT call in order to ensure that critical functions do not run without this human check in place as these may rely on key configuration. If you have a design where specific field values are critical (custom or standard) for integrity, then INIT INSERT is a dangerous default which could result in the corruption of processes. This is separate automated INIT INSERT from a setup page.</p>
|
||||
<h2 id=nav-specific-example><strong>NAV Specific Example</strong></h2>
|
||||
<h2 id=nav-specific-example>NAV Specific Example</h2>
|
||||
<p>A global variable record and a global status indicator, but within the context of a local function.</p>
|
||||
<p><a href=6332.1.png><img src=6332.1.png alt=" "></a></p>
|
||||
<p><a href=5025.2.png><img src=5025.2.png alt=" "></a></p>
|
||||
<p><img src=5672.8.png alt=" "></p>
|
||||
<h2 id=nav-usages><strong>NAV Usages</strong></h2>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>A similar example of this is in Codeunit 80, but without any validation.</p>
|
||||
<p><a href=4.png><img src=4.png alt=" "></a></p>
|
||||
<p>E.g. If there is a bespoke change, then this existing <strong>GetGLSetup</strong> can be called earlier to accommodate for an earlier bespoke change:</p>
|
||||
<p><a href=5.png></a><a href=2465.5.png><img src=2465.5.png alt=" "></a></p>
|
||||
<p>This means that by the time the code reaches the original <strong>GetGLSetup</strong> 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 <strong>not</strong> be declared locally at the same time, review your code for matching local variable usage before implementing this.</p>
|
||||
<hr>
|
||||
<h2 id=ideas-for-improvement><strong>Ideas for improvement</strong></h2>
|
||||
<h2 id=ideas-for-improvement>Ideas for improvement</h2>
|
||||
<p>Merge <strong>Singleton Table</strong> with dynamic validation field meta configuration. This removes the coding of <strong>TESTFIELD</strong> to a central setup check.</p>
|
||||
<p>Example with the <strong>Sales & Receivables Setup</strong></p>
|
||||
<p><a href=5857.1.png><img src=5857.1.png alt=" "></a></p>
|
||||
<p><a href=4477.2.png><img src=4477.2.png alt=" "></a></p>
|
||||
<p><a href=4314.3.png><img src=4314.3.png alt=" "></a></p>
|
||||
<hr>
|
||||
<h2 id=consequences><strong>Consequences</strong></h2>
|
||||
<h2 id=consequences>Consequences</h2>
|
||||
<p>If in the circumstance that a field value in the setup table is expected to change within the life of the code component instance. e.g. If a CHANGECOMPANY is required to cross reference another Setup table, use a separate variable.</p>
|
||||
<h2 id=related-topics><strong>Related Topics</strong></h2>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>This is related to the <strong>Singleton Table</strong> pattern.</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
|
|
@ -307,12 +304,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Released Entity :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/released-entity/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,8 +248,8 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage><strong>Usage</strong></a>
|
||||
<ul>
|
||||
<li><a href=#automatic-pending-or-release>Automatic pending or release</a></li>
|
||||
|
|
@ -271,10 +271,10 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Released Entity</h1>
|
||||
<p><em>Authors: Henrik Langbak and Kim Ginnerup, Bording Data</em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>This pattern prevent data from being used elsewhere before it is in a system consistent state.<br>
|
||||
NAV inserts a record as soon as the primary key has been set. But the record may not be in a valid state at this point in time. How do you know if a newly inserted record is ready for use?</p>
|
||||
<h2 id=description><strong>Description</strong></h2>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>Whenever you need to stall the release of data, you can use this pattern.</p>
|
||||
<p>Because NAV decides when a record is written to the database, it may not be in a system consistent state. Nobody should use the record before everything is in place and the record is valid. An inserted record may even have data in other tables that needs to be inserted and in a valid state before other parts of the system can use the data without running into a problem.</p>
|
||||
<p>Data entered into the system may have to be approved by a second person before it can be used.</p>
|
||||
|
|
@ -282,15 +282,28 @@ NAV inserts a record as soon as the primary key has been set. But the record may
|
|||
<p>The solution is an Option Field with two or three values:<br>
|
||||
(Open, Released) or (Open, Pending, Released)</p>
|
||||
<p>The states should be interpreted as:</p>
|
||||
<p>State</p>
|
||||
<p>Description</p>
|
||||
<p>Open</p>
|
||||
<p>Not all data is in place. The record is system inconsistent. The record or record hierarchy is invisible for all other parts of the system.</p>
|
||||
<p>Pending</p>
|
||||
<p>The record is system consistent. But is awaiting someone to manually raise the state to Released.<br>
|
||||
The record is still invisible.</p>
|
||||
<p>Released</p>
|
||||
<p>All data is in place and the record is system consistent, and ready for use. It is now visible for the rest of the system. The state can never be reversed.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Open</td>
|
||||
<td>Not all data is in place. The record is system inconsistent. The record or record hierarchy is invisible for all other parts of the system.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pending</td>
|
||||
<td>The record is system consistent. But is awaiting someone to manually raise the state to Released. The record is still invisible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Released</td>
|
||||
<td>All data is in place and the record is system consistent, and ready for use. It is now visible for the rest of the system. The state can never be reversed.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The option field name: Release State.</p>
|
||||
<p>This pattern is very similar to the Blocked Entity pattern, but it has one significant difference.<br>
|
||||
The record is not visible to any part of the system, before it is in the Released state.<br>
|
||||
|
|
@ -334,12 +347,12 @@ When talking about hierarchical data structures and the Release State is held on
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506468></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506468></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506468></script>
|
||||
<script src=/js/featherlight.min.js?1644506468></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506468></script>
|
||||
<script src=/js/relearn.js?1644506468></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Report Selection :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506468 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506468 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506468></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/report-selection/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506468></script>
|
||||
<script src=/js/auto-complete.js?1644506468></script>
|
||||
<script src=/js/search.js?1644506468></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,13 +248,13 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#meet-the-pattern><strong>Meet the Pattern</strong></a></li>
|
||||
<li><a href=#know-the-pattern><strong>Know the Pattern</strong></a></li>
|
||||
<li><a href=#use-the-pattern><strong>Use the Pattern</strong></a></li>
|
||||
<li><a href=#example><strong>Example</strong></a></li>
|
||||
<li><a href=#nav-usages><strong>NAV Usages</strong></a></li>
|
||||
<li><a href=#ideas-for-improvement><strong>Ideas for improvement</strong></a></li>
|
||||
<li><a href=#related-patterns><strong>Related Patterns</strong></a></li>
|
||||
<li><a href=#meet-the-pattern>Meet the Pattern</a></li>
|
||||
<li><a href=#know-the-pattern>Know the Pattern</a></li>
|
||||
<li><a href=#use-the-pattern>Use the Pattern</a></li>
|
||||
<li><a href=#example>Example</a></li>
|
||||
<li><a href=#nav-usages>NAV Usages</a></li>
|
||||
<li><a href=#ideas-for-improvement>Ideas for improvement</a></li>
|
||||
<li><a href=#related-patterns>Related Patterns</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -268,15 +268,15 @@ ALGuidelines.Dev
|
|||
<p>Group 1: Dale Gauci & Kimberly Congleton</p>
|
||||
<p>Group 2: Jens Winberg, Tim Grant, Alen Tot</p>
|
||||
<p>Thanks to Tim Grant who had merged the two patterns, corrected, sent for review and finalized them.</p>
|
||||
<h2 id=meet-the-pattern><strong>Meet the Pattern</strong></h2>
|
||||
<h2 id=meet-the-pattern>Meet the Pattern</h2>
|
||||
<p>It should be possible to change which document report object should be used when printing. This configuration can be stored in one place (Report Selection) and available at configuration time. In this situation, the code for printing records can remain the same.</p>
|
||||
<p>The purpose of this pattern is to describe the process to implement a reports selection by retrieving the specific <strong>Document Header</strong>, determining which type of document is related to it in the <strong>Report Selection Screen</strong>, and call the report which needs to be printed by passing the specific document header. This specifies the reports that you can print when you work with the various documents for sales and purchases, such as orders, quotes, invoices, and credit memos.</p>
|
||||
<h2 id=know-the-pattern><strong>Know the Pattern</strong></h2>
|
||||
<h2 id=know-the-pattern>Know the Pattern</h2>
|
||||
<p>The program can preselect which report will be printed when you print from various types of purchase and sales headers. For example, on an order, the <strong>Order Confirmation</strong> report is automatically printed.</p>
|
||||
<p>The <strong>Report Selection</strong> table contains the specification of which report will be printed in different situations. The <strong>Report Selection</strong> table also contains the report ID and report name for the report that will be printed when the user works with a given document type.</p>
|
||||
<p>The user can, of course, choose to have the program print a different report than the preselected one. You can also add reports to the <strong>Report Selection</strong> table to have the program print more than one report per document type.</p>
|
||||
<p>This pattern should be used when the user needs to print a new type of document which can have different report layouts, or when the user needs to print several different reports in sequence. This can also be used during a new post and print routine, a test report for journal posting or for re-printing a posted document. Using this pattern will minimize code by allowing a flexible means of specifying different reports to print, instead of hard-coding a report id when printing a document.</p>
|
||||
<h2 id=use-the-pattern><strong>Use the Pattern</strong></h2>
|
||||
<h2 id=use-the-pattern>Use the Pattern</h2>
|
||||
<p>The Report Selection Pattern involves the <strong>Report Selection</strong> table as the central configuration element also with the <strong>Report Selection</strong> Page. The table is used in 4 generic functional workflows:</p>
|
||||
<ol>
|
||||
<li>Test Print un-posted</li>
|
||||
|
|
@ -305,7 +305,7 @@ ALGuidelines.Dev
|
|||
<ul>
|
||||
<li>The specific document related posted header table is used along with a typical function: <strong>PrintRecords</strong> within the respective table.</li>
|
||||
</ul>
|
||||
<h2 id=example><strong>Example</strong></h2>
|
||||
<h2 id=example>Example</h2>
|
||||
<p>Sales Document (Invoice)</p>
|
||||
<p>Pre-conditions</p>
|
||||
<ul>
|
||||
|
|
@ -315,51 +315,46 @@ ALGuidelines.Dev
|
|||
</ul>
|
||||
<p>Implementation:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Add a new <strong>Option String</strong> to the <strong>Report Selection</strong> table, <strong>Usage</strong> field (including any ML Captions).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Calling of <strong>GetReport</strong> function, passing the document header.</p>
|
||||
<p>SalesSetup.GET;
|
||||
IF SalesSetup.“Post & Print with ob Queue” THEN
|
||||
SalesPostViaobQueue.EnqueueSalesDoc(SalesHeader)
|
||||
ELSE BEGIN
|
||||
CODEUNIT.RUN(CODEUNIT::“Sales-Post”,SalesHeader);
|
||||
GetReport(SalesHeader);
|
||||
END;
|
||||
COMMIT;</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Implementing the new document type within the <strong>GetReport</strong> Function, and calling <strong>PrintReport</strong> with the New OptionString</p>
|
||||
<p>“Document Type”::Invoice:
|
||||
BEGIN
|
||||
IF “Last Posting No.” = '' THEN
|
||||
SalesInvHeader.“No.":= “No.”
|
||||
ELSE
|
||||
SalesInvHeader.“No.” := “Last Posting No.";
|
||||
SalesInvHeader.SETRECFILTER;
|
||||
PrintReport(ReportSelection.Usage::“S.Invoice”);
|
||||
END;</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Implement the new Document Type and calling the associated report ID, passing the document header</p>
|
||||
</li>
|
||||
<li>Add a new <strong>Option String</strong> to the <strong>Report Selection</strong> table, <strong>Usage</strong> field (including any ML Captions).</li>
|
||||
<li>Calling of <strong>GetReport</strong> function, passing the document header.</li>
|
||||
</ul>
|
||||
<h2 id=nav-usages><strong>NAV Usages</strong></h2>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>SalesSetup<span style=color:#f92672>.</span>GET;
|
||||
<span style=color:#66d9ef>IF</span> SalesSetup<span style=color:#f92672>.</span>"Post & Print with ob Queue" <span style=color:#66d9ef>THEN</span>
|
||||
SalesPostViaobQueue<span style=color:#f92672>.</span>EnqueueSalesDoc<span style=color:#f92672>(</span>SalesHeader<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>ELSE</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>CODEUNIT</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>CODEUNIT</span>::"Sales-Post",SalesHeader<span style=color:#f92672>)</span>;
|
||||
GetReport<span style=color:#f92672>(</span>SalesHeader<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
COMMIT;
|
||||
</code></pre></div><ul>
|
||||
<li>Implementing the new document type within the <strong>GetReport</strong> Function, and calling <strong>PrintReport</strong> with the New OptionString</li>
|
||||
</ul>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>"Document Type"::Invoice:
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> "Last Posting No." = <span style=color:#e6db74>''</span> <span style=color:#66d9ef>THEN</span>
|
||||
SalesInvHeader<span style=color:#f92672>.</span>"No."<span style=color:#f92672>:=</span> "No."
|
||||
<span style=color:#66d9ef>ELSE</span>
|
||||
SalesInvHeader<span style=color:#f92672>.</span>"No." <span style=color:#f92672>:=</span> "Last Posting No.";
|
||||
SalesInvHeader<span style=color:#f92672>.</span>SETRECFILTER;
|
||||
PrintReport<span style=color:#f92672>(</span>ReportSelection<span style=color:#f92672>.</span>Usage::"S.Invoice"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><ul>
|
||||
<li>Implement the new Document Type and calling the associated report ID, passing the document header</li>
|
||||
</ul>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<ul>
|
||||
<li>Codeunits 82, 92, for post and printing purchase and sales documents</li>
|
||||
<li>Codeunit 229 for Document printing</li>
|
||||
<li>Header Tables 110, 112, 114, 120, 122, 124, 295, 297, 302, 304. 5744, 5746, 6650, 6660</li>
|
||||
</ul>
|
||||
<p>This pattern is already used for printing documents like sales invoices, proforma, waybills, Finance Charge Memos, Receipt Documents.</p>
|
||||
<hr>
|
||||
<h2 id=ideas-for-improvement><strong>Ideas for improvement</strong></h2>
|
||||
<h2 id=ideas-for-improvement>Ideas for improvement</h2>
|
||||
<p>The “Usage” Field could be more dynamic through a setup field linked to a document type table mapped to the document header Table ID.</p>
|
||||
<p>Report Selection table is currently based on the Usage of the report to be defined. A more generic way could be to only select what record id the printing selection is based on could also be implemented. (I think this means Recordref and Table Number could be used to identify the posted tables)</p>
|
||||
<p>The Report Selection matrix could be evolved to accommodate the Journal post & print configuration. This setup currently resides in the Gen. Journal Template table.</p>
|
||||
<p>Merge the <strong>PrintReport</strong> functions in the purchase and sales post printing functions (82, 92) into a more atomic print selection component.</p>
|
||||
<p>Merge the <strong>PrintRecords</strong> functions in the separate posted header tables into a more atomic print selection component.</p>
|
||||
<h2 id=related-patterns><strong>Related Patterns</strong></h2>
|
||||
<h2 id=related-patterns>Related Patterns</h2>
|
||||
<ul>
|
||||
<li>Posting Routine Pattern (Journal/Document)</li>
|
||||
<li>Post Batch Routine Pattern</li>
|
||||
|
|
@ -376,12 +371,12 @@ END;</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Sensitive Data Encapsulation :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -256,17 +256,10 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Sensitive Data Encapsulation</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>_<br>
|
||||
_</p>
|
||||
<p><a href=Logo-_2D00_-Protected-Data-Encapsulation.png><img src=Logo-_2D00_-Protected-Data-Encapsulation.png alt=" "></a></p>
|
||||
<p>**<br>
|
||||
**</p>
|
||||
<p><strong>Aliases:</strong> Encapsulation, Separation of Concerns [1]</p>
|
||||
<p>**<br>
|
||||
**</p>
|
||||
<p><strong>Context</strong>: You want to store and protect sensitive data which already exists in a system, but it is not clear which data needs protection and how to store it.</p>
|
||||
<p><strong>Problem</strong>: Sensitive data is scattered and mixed with other data in various parts of the system (passwords residing in the same table with non-sensitive data, part of the private information might be stored in files, hardcoded text constants, hardcoded info as part of the code etc.).</p>
|
||||
<hr>
|
||||
<p><strong>Forces:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Obscurity:</strong> sensitive data mixed with other data and code makes it hard to have an overview of what needs to be protected.</li>
|
||||
|
|
@ -276,16 +269,14 @@ _</p>
|
|||
<li><strong>Low</strong> <strong>Performance</strong>: protecting all data can slow down the system.</li>
|
||||
</ul>
|
||||
<p><strong>Solution:</strong> Extract and separate sensitive data into a single known repository.</p>
|
||||
<p>To apply this pattern in Dynamics NAV, a table structure similar to Table 1261 Service Password can be used. The Service Password table also contains additional functionality which will help to further apply related patterns like <a href=/nav/w/designpatterns/277.3-single-point-of-acces><strong>Access Control</strong></a> and <a href=/nav/w/designpatterns/276.2-data-encryption><strong>Encryption</strong></a>.</p>
|
||||
<p>To apply this pattern in Dynamics NAV, a table structure similar to Table 1261 Service Password can be used. The Service Password table also contains additional functionality which will help to further apply related patterns like <a href=/navpatterns/1-patterns/security/3-single-point-of-access/><strong>Access Control</strong></a> and <a href=/navpatterns/1-patterns/security/2-data-encryption/><strong>Encryption</strong></a>.</p>
|
||||
<p>Figure 1 describes the definition of a table which is already available in Dynamics NAV. This table can be used for storing sensitive data. As a minimum, the table only needs two fields:</p>
|
||||
<ol>
|
||||
<li>The key is of type GUID (Globally Unique Identifier), which is a 128-bit value consisting of multiple groups of hexadecimal digits [2]. Each key needs to be unique and will be used for storing and retrieving the protected information.</li>
|
||||
<li>The value (the actual data to be encapsulated) is of type BLOB (Binary Large OBject) [3], which contains the encrypted or un-encrypted data (for encryption, see the related <a href=/nav/w/designpatterns/276.2-data-encryption><strong>Encryption</strong></a> pattern).</li>
|
||||
<li>The value (the actual data to be encapsulated) is of type BLOB (Binary Large OBject) [3], which contains the encrypted or un-encrypted data (for encryption, see the related <a href=/navpatterns/1-patterns/security/2-data-encryption/><strong>Encryption</strong></a> pattern).</li>
|
||||
</ol>
|
||||
<p><a href=Data-Encapsulation-_2D00_-figure-1.png><img src=Data-Encapsulation-_2D00_-figure-1.png alt="Figure 1- Example definition, table used for Data Encapsulation"></a></p>
|
||||
<p><em>Figure 1- Example definition, table used for <strong>Sensitive</strong> <strong>Data</strong> <strong>Encapsulation</strong></em></p>
|
||||
<p>**<br>
|
||||
**</p>
|
||||
<p>Let’s use a software system (which can be a Dynamics NAV extension or customization). Chances are that the system will look similar to the one described in part 1 of Figure 2: there is data handled in various places of the system, on various storage solutions. Intertwined with normal data, there is sensitive data. For example: Dynamics CRM (Customer Relationship Management) connection information could be all stored in one table, and consists of the connection URI (normal data), enabled/disabled status (normal data), and connection password (sensitive data).</p>
|
||||
<p>Figure 2 illustrates the system before and after applying the <strong>Sensitive Data Encapsulation</strong> pattern.</p>
|
||||
<ul>
|
||||
|
|
@ -303,46 +294,33 @@ _</p>
|
|||
</ul>
|
||||
<p><a href=Multi-_2D00_-1-2.JPG><img src=Multi-_2D00_-1-2.JPG alt=" "></a></p>
|
||||
<p><em>Figure 2 - Data access before and after <strong>Sensitive</strong> <strong>Data</strong> <strong>Encapsulation.</strong></em></p>
|
||||
<p>.</p>
|
||||
<p><strong>Benefits:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Clarity:</strong> when all sensitive data is encapsulated in one place, it is clear which is the information that needs to be protected.</li>
|
||||
<li><strong>Simplicity:</strong> easier to protect just a limited number of known resources when they are grouped.</li>
|
||||
<li>**Homogeneity: **the same protection can be applied to all data, since it is stored in the same place.</li>
|
||||
<li><strong>Homogeneity:</strong> the same protection can be applied to all data, since it is stored in the same place.</li>
|
||||
<li><strong>Separation of concerns:</strong> treat each section of the computer program differently, by separating it and clearly addressing its own requirements and limitations. [1]</li>
|
||||
<li><strong>Performance</strong>: data protection techniques like <strong>Access Control</strong> and <strong>Encryption</strong> can now be applied only to the sensitive data (not to everything), which improves the performance of the system.</li>
|
||||
</ul>
|
||||
<p><strong>Drawbacks:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Single point of failure:</strong> a maliciously intended actor has no longer a need to reverse engineer the places where important data is stored. In the unwanted situation when this actor would have already obtained access to the system, they can more easily locate the sensitive information. This is a step towards information disclosure, but mechanisms like <a href=/nav/w/designpatterns/276.2-data-encryption><strong>Encryption</strong></a> and logging can provide further protection.</li>
|
||||
<li><strong>Single point of failure:</strong> a maliciously intended actor has no longer a need to reverse engineer the places where important data is stored. In the unwanted situation when this actor would have already obtained access to the system, they can more easily locate the sensitive information. This is a step towards information disclosure, but mechanisms like <a href=/navpatterns/1-patterns/security/2-data-encryption/><strong>Encryption</strong></a> and logging can provide further protection.</li>
|
||||
<li><strong>Limited Text Length</strong>: there is a limit on how long the encrypted text can be. This limit is imposed by the OS encryption service and it depends on the composition of the text as well as on the system specifics. In NAV, we had implemented the Encrypted Text for text values of max 250 chars, which is enough to cover passwords, person ID numbers, credit card info, but it might turn insufficient in other future scenarios.</li>
|
||||
<li><strong>Nomenclature</strong>: the name of the table <strong>Service Password</strong> is too specific, since it started by being used for passwords, but it has the capability and it now contains other sensitive data like API Keys, credit card numbers etc.</li>
|
||||
</ul>
|
||||
<p><strong>References</strong></p>
|
||||
<p>[1]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation>https://en.wikipedia.org/wiki/Separation</a>_of_concerns.</p>
|
||||
<p>[2]</p>
|
||||
<p>“GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary>https://en.wikipedia.org/wiki/Binary</a>_large_object.</p>
|
||||
<p>[4]</p>
|
||||
<p>waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5]</p>
|
||||
<p>Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6]</p>
|
||||
<p>B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7]</p>
|
||||
<p>“Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun>https://en.wikipedia.org/wiki/Shotgun</a>_surgery. [Accessed 31 07 2016].</p>
|
||||
<p>[8]</p>
|
||||
<p>M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9]</p>
|
||||
<p>“Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data>https://en.wikipedia.org/wiki/Data</a>_masking#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10]</p>
|
||||
<p>“Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11]</p>
|
||||
<p>“How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12]</p>
|
||||
<p>“sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef</a>_sniffer.htm. [Accessed 02 08 2016].</p>
|
||||
<p>[1] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation_of_concerns>https://en.wikipedia.org/wiki/Separation_of_concerns</a>.</p>
|
||||
<p>[2] “GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary_large_object>https://en.wikipedia.org/wiki/Binary_large_object</a>.</p>
|
||||
<p>[4] waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5] Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6] B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7] “Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun_surgery>https://en.wikipedia.org/wiki/Shotgun_surgery</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[8] M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9] “Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data_masking#Masking_out>https://en.wikipedia.org/wiki/Data_masking#Masking_out</a>. [Accessed 29 7 2016].</p>
|
||||
<p>[10] “Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11] “How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12] “sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm</a>. [Accessed 02 08 2016].</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -355,12 +333,12 @@ _</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Data Encryption :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/2-data-encryption/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -256,61 +256,86 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Data Encryption</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>__</p>
|
||||
<p>_<a href=Logo-_2D00_-Encryption.png><img src=Logo-_2D00_-Encryption.png alt=" "></a><br>
|
||||
_</p>
|
||||
<hr>
|
||||
<p><strong>Context</strong>: After applying <a href=/nav/w/designpatterns/275.1-sensitive-data-encapsulation><strong>Sensitive Data Encapsulation</strong></a>, all sensitive data is gathered in a known place in the database. This makes it possible to apply further protection best practices.</p>
|
||||
<p><a href=Logo-_2D00_-Encryption.png><img src=Logo-_2D00_-Encryption.png alt=" "></a></p>
|
||||
<p><strong>Context</strong>: After applying <a href=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/><strong>Sensitive Data Encapsulation</strong></a>, all sensitive data is gathered in a known place in the database. This makes it possible to apply further protection best practices.</p>
|
||||
<p><strong>Problem</strong>: If any non-authorized actor manages to get access to a copy of the database, the sensitive data is immediately available in clear-text.</p>
|
||||
<p>**<br>
|
||||
**</p>
|
||||
<p><strong>Forces:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Accessibility:</strong> anyone who managed to steal a copy of the database can at once read the sensitive information.</li>
|
||||
</ul>
|
||||
<p><strong>Solution:</strong> Encrypt sensitive data. Dynamics NAV offers a simple mechanism for data encryption, to be used by NAV developers.</p>
|
||||
<p>Figure 1 adds one more step (in continuation of the figure in pattern <strong><a href=/nav/w/designpatterns/275.sensitive-data-encapsulation>Sensitive Data Encapsulation</a></strong>), in which the first two panels describe how sensitive data has all been gathered in one known place. This makes the current pattern, <strong>Encryption</strong>, much easier – since now data needs to be encrypted in only one place. The last panel of Figure 1 shows the system after the next step, <strong>Encryption</strong>, has been implemented. This shows the iterative process of applying patterns and making the code better step by step.</p>
|
||||
<p>Figure 1 adds one more step (in continuation of the figure in pattern <strong><a href=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/>Sensitive Data Encapsulation</a></strong>), in which the first two panels describe how sensitive data has all been gathered in one known place. This makes the current pattern, <strong>Encryption</strong>, much easier – since now data needs to be encrypted in only one place. The last panel of Figure 1 shows the system after the next step, <strong>Encryption</strong>, has been implemented. This shows the iterative process of applying patterns and making the code better step by step.</p>
|
||||
<p><a href=Multi-_2D00_-1-2-3.JPG><img src=Multi-_2D00_-1-2-3.JPG alt=" "></a></p>
|
||||
<p><em>Figure 1- <strong>Encryption</strong> becomes easier after first applying <a href=/nav/w/designpatterns/275.1-sensitive-data-encapsulation><strong>Sensitive Data Encapsulation</strong></a>.</em></p>
|
||||
<hr>
|
||||
<p><em>Figure 1- <strong>Encryption</strong> becomes easier after first applying <a href=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/><strong>Sensitive Data Encapsulation</strong></a>.</em></p>
|
||||
<p><strong>Usage</strong>: in Dynamics NAV, codeunit 1266 Encryption Management offers an API for encryption of data. The available functionality is described in Table 1.</p>
|
||||
<p>Table 1- Encryption functionality in Dynamics NAV (found in codeunit 1266 Encryption Management)</p>
|
||||
<p><strong>Procedure</strong></p>
|
||||
<p><strong>Description</strong></p>
|
||||
<p><strong>EnableEncryption</strong></p>
|
||||
<p>Confirms with the user before enabling encryption in all companies of the current database.</p>
|
||||
<p><strong>EnableEncryptionSilently</strong></p>
|
||||
<p>Enables encryption without UI interaction (to be used for web services).</p>
|
||||
<p><strong>DisableEncryption</strong></p>
|
||||
<p>Disables encryption. Has a boolean “Silent” parameter which enables/disables UI interaction.</p>
|
||||
<p><strong>Encrypt</strong></p>
|
||||
<p>Checks that encryption is possible before encrypting the given text.</p>
|
||||
<p><strong>Decrypt</strong></p>
|
||||
<p>Checks that encryption is possible before decrypting the given text.</p>
|
||||
<p><strong>ExportKey</strong></p>
|
||||
<p>If encryption is possible, it shows a confirmation dialog to confirm the export of the encryption key, and proceeds to saving it to a location chosen by the user.</p>
|
||||
<p><strong>ImportKey</strong></p>
|
||||
<p>Imports the encryption key from a user chosen location.</p>
|
||||
<p><strong>ChangeKey</strong></p>
|
||||
<p>Changes the encryption key.</p>
|
||||
<p><strong>IsEncryptionEnabled</strong></p>
|
||||
<p>Returns TRUE is encryption is enabled.</p>
|
||||
<p><strong>IsEncryptionPossible</strong></p>
|
||||
<p>Check is the correct key is present, which only works if encryption is enabled.</p>
|
||||
<p><strong>DeleteEncryptedDataInAllCompanies</strong></p>
|
||||
<p>Confirms through UI and if the user agrees, deletes all data stored in the Service Password table for all companies in the current database. At the end, it deletes the encryption key.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Procedure</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>EnableEncryption</td>
|
||||
<td>Confirms with the user before enabling encryption in all companies of the current database.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EnableEncryptionSilently</td>
|
||||
<td>Enables encryption without UI interaction (to be used for web services).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DisableEncryption</td>
|
||||
<td>Disables encryption. Has a boolean “Silent” parameter which enables/disables UI interaction.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Encrypt</td>
|
||||
<td>Checks that encryption is possible before encrypting the given text.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Decrypt</td>
|
||||
<td>Checks that encryption is possible before decrypting the given text.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ExportKey</td>
|
||||
<td>If encryption is possible, it shows a confirmation dialog to confirm the export of the encryption key, and proceeds to saving it to a location chosen by the user.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ImportKey</td>
|
||||
<td>Imports the encryption key from a user chosen location.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ChangeKey</td>
|
||||
<td>Changes the encryption key.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IsEncryptionEnabled</td>
|
||||
<td>Returns TRUE is encryption is enabled.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IsEncryptionPossible</td>
|
||||
<td>Check is the correct key is present, which only works if encryption is enabled.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DeleteEncryptedDataInAllCompanies</td>
|
||||
<td>Confirms through UI and if the user agrees, deletes all data stored in the Service Password table for all companies in the current database. At the end, it deletes the encryption key.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>User confirmation of encryption</strong></p>
|
||||
<p>Ideally, encryption should be enabled by default.</p>
|
||||
<p>However, in some versions of Dynamics NAV, there are places where any user who happens to hit a sensitive field (like a password) is asked if they want to encrypt or not. If user confirmation is needed, then let only the security administrators decide (not any random user).</p>
|
||||
<p>To ask the security administrator if they want to enable encryption, plug the code below into the OnValidate trigger of the data field which is to be encrypted. This trigger will then get executed each time there’s a change on the password field. For example, if the user is entering a password, then add a call to this procedure to Password – OnValidate() trigger:</p>
|
||||
<p>EncryptionIsNotActivatedQst@1001 : TextConst ‘ENU=Data encryption is not activated. It is recommended that you encrypt data. \Do you want to open the Data Encryption Management window?';</p>
|
||||
<p>LOCAL PROCEDURE CheckEncryption@6();</p>
|
||||
<p>BEGIN</p>
|
||||
<p>IF NOT ENCRYPTIONENABLED THEN</p>
|
||||
<p>IF CONFIRM(EncryptionIsNotActivatedQst) THEN</p>
|
||||
<p>PAGE.RUN(PAGE::“Data Encryption Management”);</p>
|
||||
<p>END;</p>
|
||||
<p>The code above will guide the user on encrypting, storing the encryption key and choosing a safe password, as follows. Consider for example that NAV is used by a small business, where Stan is the business owner. Hence, Stan has access to all NAV setup and security decisions. Stan wants to enable a connection between NAV and CRM. In NAV, he opens page CRM Connection Setup and enters the URL, user name and password for CRM (Figure 10). When Stan leaves the password field, if data encryption is not enabled, then he sees the confirmation message in Figure 2.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>EncryptionIsNotActivatedQst@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>TextConst</span> <span style=color:#e6db74>'ENU=Data encryption is not activated. It is recommended that you encrypt data. \\Do you want to open the Data Encryption Management window?'</span>;
|
||||
|
||||
<span style=color:#66d9ef>LOCAL</span> <span style=color:#66d9ef>PROCEDURE</span> CheckEncryption@<span style=color:#ae81ff>6</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> ENCRYPTIONENABLED <span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>IF</span> CONFIRM<span style=color:#f92672>(</span>EncryptionIsNotActivatedQst<span style=color:#f92672>) </span><span style=color:#66d9ef>THEN</span>
|
||||
<span style=color:#66d9ef>PAGE</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span><span style=color:#66d9ef>PAGE</span>::"Data Encryption Management"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>The code above will guide the user on encrypting, storing the encryption key and choosing a safe password, as follows. Consider for example that NAV is used by a small business, where Stan is the business owner. Hence, Stan has access to all NAV setup and security decisions. Stan wants to enable a connection between NAV and CRM. In NAV, he opens page CRM Connection Setup and enters the URL, user name and password for CRM (Figure 10). When Stan leaves the password field, if data encryption is not enabled, then he sees the confirmation message in Figure 2.</p>
|
||||
<p><a href=Encryption-_2D00_-1.JPG><img src=Encryption-_2D00_-1.JPG alt=" "></a></p>
|
||||
<p><em>Figure 2- The administrator is advised to enable encryption.</em></p>
|
||||
<p>Now Stan becomes aware that there is no encryption and has the opportunity to enable it. If he clicks on “Yes”, Stan will be taken to the Data Encryption Management page (Figure 3).</p>
|
||||
|
|
@ -340,34 +365,22 @@ _</p>
|
|||
<p><strong>Anti-patterns:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Performance:</strong> Do not encrypt everything, because it will have a performance impact on the system. Only important information should be encrypted.</li>
|
||||
<li><strong>System calls and “Do It Yourself” solutions</strong>: Although system calls for encryptions are available in NAV (ENCRYPT, DECRYPT and <action>ENCRYPTIONKEY), unless there is no other way, refrain from using them directly. Use instead he API in codeunit 1266 Encryption Management, which is safer to use, because it protects against common mistakes (like attempting to encrypt an already encrypted string, enabling encryption in only one company which makes data not usable in another on the same tenant etc.). Use the <a href=/nav/w/designpatterns/277.3-single-point-of-acces><strong>Single Point of Access</strong></a> pattern to handle sensitive data which needs to be encrypted.</li>
|
||||
<li><strong>System calls and “Do It Yourself” solutions</strong>: Although system calls for encryptions are available in NAV (ENCRYPT, DECRYPT and <action>ENCRYPTIONKEY), unless there is no other way, refrain from using them directly. Use instead he API in codeunit 1266 Encryption Management, which is safer to use, because it protects against common mistakes (like attempting to encrypt an already encrypted string, enabling encryption in only one company which makes data not usable in another on the same tenant etc.). Use the <a href=/navpatterns/1-patterns/security/3-single-point-of-access/><strong>Single Point of Access</strong></a> pattern to handle sensitive data which needs to be encrypted.</li>
|
||||
<li><strong>System-level encryption.</strong> The similar codeunit API 1803 Encrypted Key/Value Management is not intended to be reused by partner NAV developers. Normal NAV users do not have permission to access this resource. This stores sensitive data to be accessed by system NAV functionality.</li>
|
||||
</ul>
|
||||
<p><strong>References</strong></p>
|
||||
<p>[1]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation>https://en.wikipedia.org/wiki/Separation</a>_of_concerns.</p>
|
||||
<p>[2]</p>
|
||||
<p>“GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary>https://en.wikipedia.org/wiki/Binary</a>_large_object.</p>
|
||||
<p>[4]</p>
|
||||
<p>waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5]</p>
|
||||
<p>Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6]</p>
|
||||
<p>B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7]</p>
|
||||
<p>“Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun>https://en.wikipedia.org/wiki/Shotgun</a>_surgery. [Accessed 31 07 2016].</p>
|
||||
<p>[8]</p>
|
||||
<p>M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9]</p>
|
||||
<p>“Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data>https://en.wikipedia.org/wiki/Data</a>_masking#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10]</p>
|
||||
<p>“Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11]</p>
|
||||
<p>“How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12]</p>
|
||||
<p>“sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef</a>_sniffer.htm. [Accessed 02 08 2016].</p>
|
||||
<p>[1] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation_of_concerns>https://en.wikipedia.org/wiki/Separation_of_concerns</a>.</p>
|
||||
<p>[2] “GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary_large_object>https://en.wikipedia.org/wiki/Binary_large_object</a>.</p>
|
||||
<p>[4] waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5] Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6] B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7] “Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun_surgery>https://en.wikipedia.org/wiki/Shotgun_surgery</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[8] M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9] “Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data_masking#Masking_out>https://en.wikipedia.org/wiki/Data_masking#Masking_out</a>. [Accessed 29 7 2016].</p>
|
||||
<p>[10] “Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11] “How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12] “sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm</a>. [Accessed 02 08 2016].</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -380,12 +393,12 @@ _</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Single Point of Access :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/3-single-point-of-access/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -256,12 +256,9 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Single Point of Access</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>_<a href=Logo-_2D00_-Single-Point-of-Access.png><img src=Logo-_2D00_-Single-Point-of-Access.png alt=" "></a><br>
|
||||
_</p>
|
||||
<p>__</p>
|
||||
<p><a href=Logo-_2D00_-Single-Point-of-Access.png><img src=Logo-_2D00_-Single-Point-of-Access.png alt=" "></a></p>
|
||||
<p><strong>Context</strong>: Protected data needs to be used. There are many types of entities which might attempt to use the data.</p>
|
||||
<p><strong>Problem</strong>: If no standard way of accessing data exists, then each entity might attempt to build its own system for handing the sensitive data. The data access layer might be implemented over and over again by each entity, without reuse of known best practices and with a lot of code duplication.</p>
|
||||
<hr>
|
||||
<p><strong>Forces:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Code duplication:</strong> if each entity attempts to write its own routines for data access, invariably this will bring duplication.</li>
|
||||
|
|
@ -273,8 +270,8 @@ _</p>
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p><strong>Solution:</strong> In Dynamics NAV the same library which offers <a href=/nav/w/designpatterns/276.2-data-encryption><strong>Encryption</strong></a>, is also intended to be used as a <strong>Single Point of Access</strong>. Write code to create, read and remove sensitive data only through codeunit 1266 Encryption Management, and never directly.</p>
|
||||
<p>In Figure 9 (figure numbering is continued from pattern <strong><a href=/nav/w/designpatterns/276.encryption>Encryption</a></strong>), the panels 1, 2 and 3 have applied the <a href=/nav/w/designpatterns/275.1-sensitive-data-encapsulation><strong>Sensitive Data Encapsulation</strong></a> and <a href=/nav/w/designpatterns/276.2-data-encryption><strong>Encryption</strong> </a>patterns. Once data is encapsulated, no matter if it has been encrypted or not, the next pattern, <strong>Single Point of Access</strong>, becomes available as seen in the panels 2 and 3 of Figure 1.</p>
|
||||
<p><strong>Solution:</strong> In Dynamics NAV the same library which offers <a href=/navpatterns/1-patterns/security/2-data-encryption/><strong>Encryption</strong></a>, is also intended to be used as a <strong>Single Point of Access</strong>. Write code to create, read and remove sensitive data only through codeunit 1266 Encryption Management, and never directly.</p>
|
||||
<p>In Figure 9 (figure numbering is continued from pattern <strong><a href=/navpatterns/1-patterns/security/2-data-encryption/>Encryption</a></strong>), the panels 1, 2 and 3 have applied the <a href=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/><strong>Sensitive Data Encapsulation</strong></a> and <a href=/navpatterns/1-patterns/security/2-data-encryption/><strong>Encryption</strong></a> patterns. Once data is encapsulated, no matter if it has been encrypted or not, the next pattern, <strong>Single Point of Access</strong>, becomes available as seen in the panels 2 and 3 of Figure 1.</p>
|
||||
<p>You can observe that, in panel 3, each usage needs to access separately the encrypted data. This means that each usage needs to implement again the encryption capabilities. This is resolved in panel 4, where all users access one common API which encrypts, hence the workload of encryption is moved from the usages, to the API, and needs to be implemented only once.</p>
|
||||
<p><a href=Multi-_2D00_-1-2-3-4.JPG><img src=Multi-_2D00_-1-2-3-4.JPG alt=" "></a></p>
|
||||
<p><em>Figure 1- <strong>Single Point of Access</strong> pattern applied.</em></p>
|
||||
|
|
@ -296,30 +293,18 @@ _</p>
|
|||
<li><strong>Single point of failure:</strong> A defect in the access library will affect all usages until it is found and fixed.</li>
|
||||
</ul>
|
||||
<p><strong>References</strong></p>
|
||||
<p>[1]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation>https://en.wikipedia.org/wiki/Separation</a>_of_concerns.</p>
|
||||
<p>[2]</p>
|
||||
<p>“GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary>https://en.wikipedia.org/wiki/Binary</a>_large_object.</p>
|
||||
<p>[4]</p>
|
||||
<p>waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5]</p>
|
||||
<p>Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6]</p>
|
||||
<p>B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7]</p>
|
||||
<p>“Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun>https://en.wikipedia.org/wiki/Shotgun</a>_surgery. [Accessed 31 07 2016].</p>
|
||||
<p>[8]</p>
|
||||
<p>M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9]</p>
|
||||
<p>“Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data>https://en.wikipedia.org/wiki/Data</a>_masking#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10]</p>
|
||||
<p>“Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11]</p>
|
||||
<p>“How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12]</p>
|
||||
<p>“sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef</a>_sniffer.htm. [Accessed 02 08 2016].</p>
|
||||
<p>[1] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation_of_concerns>https://en.wikipedia.org/wiki/Separation_of_concerns</a>.</p>
|
||||
<p>[2] “GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary_large_object>https://en.wikipedia.org/wiki/Binary_large_object</a>.</p>
|
||||
<p>[4] waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5] Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6] B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7] “Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun_surgery>https://en.wikipedia.org/wiki/Shotgun_surgery</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[8] M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9] “Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data_masking#Masking_out>https://en.wikipedia.org/wiki/Data_masking#Masking_out</a>. [Accessed 29 7 2016].</p>
|
||||
<p>[10] “Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11] “How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12] “sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm</a>. [Accessed 02 08 2016].</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -332,12 +317,12 @@ _</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Masked Text :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/4-masked-text/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -256,13 +256,10 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Masked Text</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>_<a href=Logo-_2D00_-Masked-Text.png><img src=Logo-_2D00_-Masked-Text.png alt=" "></a><br>
|
||||
_</p>
|
||||
<p>__</p>
|
||||
<p><a href=Logo-_2D00_-Masked-Text.png><img src=Logo-_2D00_-Masked-Text.png alt=" "></a></p>
|
||||
<p><strong>Aliases:</strong> Masking out</p>
|
||||
<p><strong>Context</strong>: In the user interface (UI) of a software system, the user enters protected information such as a password, an access key, a credit card number etc.</p>
|
||||
<p><strong>Problem</strong>: The entered information is visible during data entry and whenever any user (the one who entered the data, or a foreign user) opens the UI.</p>
|
||||
<hr>
|
||||
<p><strong>Forces:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Information disclosure:</strong> sensitive data is visible in the UI.</li>
|
||||
|
|
@ -272,9 +269,13 @@ _</p>
|
|||
<p><a href=Masking-_2D00_-CRM-Connection-Setup-page.PNG><img src=Masking-_2D00_-CRM-Connection-Setup-page.PNG alt=" "></a></p>
|
||||
<p><em>Figure 1 - The field “Password” is masked.</em></p>
|
||||
<p>To apply this pattern in Dynamics NAV, the developer has two choices:</p>
|
||||
<p><strong>1.</strong> <strong>Mask everywhere</strong></p>
|
||||
<ol>
|
||||
<li><strong>Mask everywhere</strong></li>
|
||||
</ol>
|
||||
<p>Mask the field in all pages which expose it or will expose it in the future. In this case, masking needs to be set at the table level, by opening the table in design mode and setting the field’s property ExtendedDatatype=Masked.</p>
|
||||
<p><strong>2.</strong> <strong>Mask only in selected pages</strong></p>
|
||||
<ol start=2>
|
||||
<li><strong>Mask only in selected pages</strong></li>
|
||||
</ol>
|
||||
<p>Mask the field in only a subset of pages. Open the pages where the field should be masked in design mode, open the property page for the field in question, and set ExtendedDatatype=Masked. This option can be used for example when a field should be hidden from most users (in most usual pages), but still visible to administrators in specific pages.</p>
|
||||
<p><strong>Benefits:</strong></p>
|
||||
<ul>
|
||||
|
|
@ -285,30 +286,18 @@ _</p>
|
|||
<li><strong>“Forgotten password”:</strong> the text in a masked field is hidden from all users, including users who theoretically have the right to see it. In this case, if the developer wishes to disclose the text only to certain users, they have to write extra code (like a lookup trigger) which will verify the user’s permissions and if permitted, show or send the clear-text value to the user who requested it.</li>
|
||||
</ul>
|
||||
<p><strong>References</strong></p>
|
||||
<p>[1]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation>https://en.wikipedia.org/wiki/Separation</a>_of_concerns.</p>
|
||||
<p>[2]</p>
|
||||
<p>“GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary>https://en.wikipedia.org/wiki/Binary</a>_large_object.</p>
|
||||
<p>[4]</p>
|
||||
<p>waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5]</p>
|
||||
<p>Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6]</p>
|
||||
<p>B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7]</p>
|
||||
<p>“Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun>https://en.wikipedia.org/wiki/Shotgun</a>_surgery. [Accessed 31 07 2016].</p>
|
||||
<p>[8]</p>
|
||||
<p>M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9]</p>
|
||||
<p>“Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data>https://en.wikipedia.org/wiki/Data</a>_masking#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10]</p>
|
||||
<p>“Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11]</p>
|
||||
<p>“How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12]</p>
|
||||
<p>“sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef</a>_sniffer.htm. [Accessed 02 08 2016].</p>
|
||||
<p>[1] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation_of_concerns>https://en.wikipedia.org/wiki/Separation_of_concerns</a>.</p>
|
||||
<p>[2] “GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary_large_object>https://en.wikipedia.org/wiki/Binary_large_object</a>.</p>
|
||||
<p>[4] waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5] Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6] B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7] “Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun_surgery>https://en.wikipedia.org/wiki/Shotgun_surgery</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[8] M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9] “Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data_masking>https://en.wikipedia.org/wiki/Data_masking</a>#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10] “Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11] “How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12] “sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm</a>. [Accessed 02 08 2016].</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -321,12 +310,12 @@ _</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>SSL in NAV :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/5-ssl-in-nav/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -256,9 +256,7 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>SSL in NAV</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p>_<a href=Logo-_2D00_-SSL.JPG><img src=Logo-_2D00_-SSL.JPG alt=" "></a><br>
|
||||
_</p>
|
||||
<p>__</p>
|
||||
<p><a href=Logo-_2D00_-SSL.JPG><img src=Logo-_2D00_-SSL.JPG alt=" "></a></p>
|
||||
<p><strong>Context</strong>: The security of data transmission is just as important as the security of data storage. When data is transmitted over the web, Secure Sockets Layer (SSL) is available to be used with the web client in Dynamics NAV. Microsoft’s NAV cloud solution has SSL enabled by default. However, if a partner company chooses to deploy their own NAV, then they need to handle SSL explicitly.</p>
|
||||
<p><strong>Problem</strong>: Although data is stored securely, before it even gets to be stored, it needs to travel the web on a client-server connection, where it is vulnerable.</p>
|
||||
<p><strong>Forces:</strong></p>
|
||||
|
|
@ -269,7 +267,7 @@ _</p>
|
|||
<p><strong>Solution:</strong> To protect the data before it reaches the server, remember to configure SSL (Secure Sockets Layer) in Dynamics NAV.</p>
|
||||
<p><em>SSL</em> is a web protocol that encrypts data that is transmitted over a network to make the data and the network more secure and reliable. A website that is enabled with SSL uses Hypertext Transfer Protocol Secure (HTTPS) instead of Hypertext Transfer Protocol (HTTP) as a communication protocol.</p>
|
||||
<p>Figure 1 shows data communication between the client (where the user enters data) and the server (which connects further to the database). Without encryption (left side), data is available in clear text over the wire. A person equipped with a network sniffer can easily intercept and read it. On the right side of the picture, SSL is used to encrypt the user’s data. Sniffing the traffic would capture the encrypted stream, but access to the real content would be impeded by encryption.</p>
|
||||
<p>**<a href=SSL-_2D00_-before-and-after.PNG><img src=SSL-_2D00_-before-and-after.PNG alt=" "></a>**</p>
|
||||
<p><a href=SSL-_2D00_-before-and-after.PNG><img src=SSL-_2D00_-before-and-after.PNG alt=" "></a></p>
|
||||
<p><em>Figure 1 - Data transmission before (http://…) and after SSL encryption (https://…).</em></p>
|
||||
<p><strong>Usage</strong>: the latest information about how to configure SSL for the web client in Dynamics NAV is found online at on MSDN at <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>.</p>
|
||||
<p><strong>Benefits:</strong></p>
|
||||
|
|
@ -282,30 +280,18 @@ _</p>
|
|||
<li><strong>Extra work:</strong> there is extra effort to enable SSL on a self-administered NAV system. The good news is that Microsoft’s cloud NAV solution has SSL by default and no extra work is required from the developer on that aspect.</li>
|
||||
</ul>
|
||||
<p><strong>References</strong></p>
|
||||
<p>[1]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation>https://en.wikipedia.org/wiki/Separation</a>_of_concerns.</p>
|
||||
<p>[2]</p>
|
||||
<p>“GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3]</p>
|
||||
<p>“Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary>https://en.wikipedia.org/wiki/Binary</a>_large_object.</p>
|
||||
<p>[4]</p>
|
||||
<p>waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5]</p>
|
||||
<p>Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6]</p>
|
||||
<p>B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7]</p>
|
||||
<p>“Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun>https://en.wikipedia.org/wiki/Shotgun</a>_surgery. [Accessed 31 07 2016].</p>
|
||||
<p>[8]</p>
|
||||
<p>M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9]</p>
|
||||
<p>“Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data>https://en.wikipedia.org/wiki/Data</a>_masking#Masking_out. [Accessed 29 7 2016].</p>
|
||||
<p>[10]</p>
|
||||
<p>“Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11]</p>
|
||||
<p>“How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12]</p>
|
||||
<p>“sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef</a>_sniffer.htm. [Accessed 02 08 2016].</p>
|
||||
<p>[1] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Separation_of_concerns>https://en.wikipedia.org/wiki/Separation_of_concerns</a>.</p>
|
||||
<p>[2] “GUID Structure,” [Online]. Available: <a href=https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx>https://msdn.microsoft.com/en-us/library/aa373931(VS.85).aspx</a>.</p>
|
||||
<p>[3] “Wikipedia,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Binary_large_object>https://en.wikipedia.org/wiki/Binary_large_object</a>.</p>
|
||||
<p>[4] waldo, “How Do I: Manage Companies in Microsoft Dynamics NAV 2013 R2”.</p>
|
||||
<p>[5] Microsoft, “Multitenant Deployment Architecture,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/dn271675(v=nav.90).aspx</a>.</p>
|
||||
<p>[6] B. Botez, “Setup Table design pattern,” Microsoft, 2013. [Online]. Available: <a href=https://community.dynamics.com/nav/w/designpatterns/76.setup-table>https://community.dynamics.com/nav/w/designpatterns/76.setup-table</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[7] “Shotgun Surgery,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Shotgun_surgery>https://en.wikipedia.org/wiki/Shotgun_surgery</a>. [Accessed 31 07 2016].</p>
|
||||
<p>[8] M. Fowler, Refactoring: Improving the design of existing code, Addison Wesley, 1999.</p>
|
||||
<p>[9] “Masking out,” [Online]. Available: <a href=https://en.wikipedia.org/wiki/Data_masking#Masking_out>https://en.wikipedia.org/wiki/Data_masking#Masking_out</a>. [Accessed 29 7 2016].</p>
|
||||
<p>[10] “Key Vault,” Microsoft, [Online]. Available: <a href=https://azure.microsoft.com/en-us/services/key-vault/>https://azure.microsoft.com/en-us/services/key-vault/</a>.</p>
|
||||
<p>[11] “How to: Configure SSL to Secure the Connection to Microsoft Dynamics NAV Web Client,” Microsoft, [Online]. Available: <a href="https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx">https://msdn.microsoft.com/en-us/library/hh167264(v=nav.90).aspx</a>. [Accessed 2 8 2016].</p>
|
||||
<p>[12] “sniffer,” [Online]. Available: <a href=http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm>http://compnetworking.about.com/od/networksecurityprivacy/g/bldef_sniffer.htm</a>. [Accessed 02 08 2016].</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -318,12 +304,12 @@ _</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/security/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Security :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/security/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -269,11 +269,11 @@ ALGuidelines.Dev
|
|||
<p>When sensitive data is stored inside the Dynamics NAV database, if negligently handled, it can become vulnerable. Particularly, the location, access and the state of the data are critical.</p>
|
||||
<p>Use the following patterns to enhance security on your NAV system.</p>
|
||||
<ol>
|
||||
<li><a href=/nav/w/designpatterns/275.sensitive-data-encapsulation>Sensitive Data Encapsulation</a></li>
|
||||
<li><a href=/nav/w/designpatterns/276.encryption>Data Encryption</a></li>
|
||||
<li><a href=/nav/w/designpatterns/277.single-point-of-access>Single Point of Access</a></li>
|
||||
<li><a href=/nav/w/designpatterns/278.masked-text>Masked Text</a></li>
|
||||
<li><a href=/nav/w/designpatterns/279.ssl-in-nav>SSL in NAV</a></li>
|
||||
<li><a href=/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/>Sensitive Data Encapsulation</a></li>
|
||||
<li><a href=/navpatterns/1-patterns/security/2-data-encryption/>Data Encryption</a></li>
|
||||
<li><a href=/navpatterns/1-patterns/security/3-single-point-of-access/>Single Point of Access</a></li>
|
||||
<li><a href=/navpatterns/1-patterns/security/4-masked-text/>Masked Text</a></li>
|
||||
<li><a href=/navpatterns/1-patterns/security/5-ssl-in-nav/>SSL in NAV</a></li>
|
||||
</ol>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
|
|
@ -287,12 +287,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,36 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Security on AL Guidelines</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/</link><description>Recent content in Security on AL Guidelines</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://alguidelines.dev/navpatterns/1-patterns/security/index.xml" rel="self" type="application/rss+xml"/><item><title>Sensitive Data Encapsulation</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/security/1-sensitive-data-encapsulation/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
_
|
||||
_
|
||||
**
|
||||
**
|
||||
Aliases: Encapsulation, Separation of Concerns [1]
|
||||
**
|
||||
**
|
||||
Context: You want to store and protect sensitive data which already exists in a system, but it is not clear which data needs protection and how to store it.
|
||||
Problem: Sensitive data is scattered and mixed with other data in various parts of the system (passwords residing in the same table with non-sensitive data, part of the private information might be stored in files, hardcoded text constants, hardcoded info as part of the code etc.</description></item><item><title>Data Encryption</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/2-data-encryption/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/security/2-data-encryption/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
__
|
||||
_
|
||||
_
|
||||
Context: After applying Sensitive Data Encapsulation, all sensitive data is gathered in a known place in the database. This makes it possible to apply further protection best practices.
|
||||
Problem: If any non-authorized actor manages to get access to a copy of the database, the sensitive data is immediately available in clear-text.
|
||||
**
|
||||
**
|
||||
Forces:
|
||||
Accessibility: anyone who managed to steal a copy of the database can at once read the sensitive information.</description></item><item><title>Single Point of Access</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/3-single-point-of-access/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/security/3-single-point-of-access/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
_
|
||||
_
|
||||
__
|
||||
Context: Protected data needs to be used. There are many types of entities which might attempt to use the data.
|
||||
Problem: If no standard way of accessing data exists, then each entity might attempt to build its own system for handing the sensitive data. The data access layer might be implemented over and over again by each entity, without reuse of known best practices and with a lot of code duplication.</description></item><item><title>Masked Text</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/4-masked-text/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/security/4-masked-text/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
_
|
||||
_
|
||||
__
|
||||
Aliases: Masking out
|
||||
Context: In the user interface (UI) of a software system, the user enters protected information such as a password, an access key, a credit card number etc.
|
||||
Problem: The entered information is visible during data entry and whenever any user (the one who entered the data, or a foreign user) opens the UI.
|
||||
Forces:
|
||||
Information disclosure: sensitive data is visible in the UI.</description></item><item><title>SSL in NAV</title><link>https://alguidelines.dev/navpatterns/1-patterns/security/5-ssl-in-nav/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/security/5-ssl-in-nav/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
_
|
||||
_
|
||||
__
|
||||
Context: The security of data transmission is just as important as the security of data storage. When data is transmitted over the web, Secure Sockets Layer (SSL) is available to be used with the web client in Dynamics NAV. Microsoft&rsquo;s NAV cloud solution has SSL enabled by default. However, if a partner company chooses to deploy their own NAV, then they need to handle SSL explicitly.</description></item></channel></rss>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Setup Specificity Fallback :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/setup-specificity-fallback/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,10 +248,10 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract><strong>Abstract</strong></a></li>
|
||||
<li><a href=#description><strong>Description</strong></a></li>
|
||||
<li><a href=#usage><strong>Usage</strong></a></li>
|
||||
<li><a href=#nav-usages><strong>NAV Usages</strong></a></li>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a></li>
|
||||
<li><a href=#nav-usages>NAV Usages</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -262,40 +262,51 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Setup Specificity Fallback</h1>
|
||||
<p><em>By Jan Hoek at IDYN</em></p>
|
||||
<h2 id=abstract><strong>Abstract</strong></h2>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>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.</p>
|
||||
<h2 id=description><strong>Description</strong></h2>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>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.</p>
|
||||
<p>With the Setup Specificity Pattern in place, primary key fields in the setup table can have a special value (typically: zero or an empty string) that acts as a wildcard, meaning that the setup record in question applies to a combination of primary key fields with any value in the field containing that wildcard. According to the pattern, when querying the setup table, the application attempts to find the appropriate setup record by searching less and less specific, starting with only specified primary key values, and possibly ending with only wildcard values, replacing specific values with wildcards in a predefined order until a setup record is found, e.g.:</p>
|
||||
<p>Step 1.</p>
|
||||
<p>Try to find record with:<br>
|
||||
Field A = value “a”<br>
|
||||
Field B = value “b”
|
||||
If found, return record; if not, go to step 2.
|
||||
Step 2.</p>
|
||||
<p>Try to find record with:<br>
|
||||
Field A = value “a”<br>
|
||||
Field B = wildcard value
|
||||
If found, return record; if not, go to step 3.
|
||||
Step 3.
|
||||
Try to find record with:<br>
|
||||
Field A = wildcard value<br>
|
||||
Field B = value “b”
|
||||
If found, return record; if not, go to step 4.
|
||||
Step 4.
|
||||
Try to find record with:<br>
|
||||
Field A = wildcard value<br>
|
||||
Field B = wildcard value<br>
|
||||
If found, return record; if not, optionally return hard-coded value</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Step 1.</td>
|
||||
<td>Try to find record with: Field A = value “a” and Field B = value “b”</td>
|
||||
<td>If found, return record; if not, go to step 2.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Step 2.</td>
|
||||
<td>Try to find record with: Field A = value “a” and Field B = wildcard value</td>
|
||||
<td>If found, return record; if not, go to step 3.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Step 3.</td>
|
||||
<td>Try to find record with: Field A = wildcard value and Field B = value “b”</td>
|
||||
<td>If found, return record; if not, go to step 4.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Step 4.</td>
|
||||
<td>Try to find record with: Field A = wildcard value and Field B = wildcard value</td>
|
||||
<td>If found, return record; if not, optionally return hard-coded value</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The least specific record can be thought of as the general rule, and each of the subsequent records is an exception to that rule. By defining only exceptions to the rule, instead of each and every combination, the burden of setting up and maintaining the setup records is strongly reduced, and the overall setup is much easier to read and understand.</p>
|
||||
<h2 id=usage><strong>Usage</strong></h2>
|
||||
<h2 id=usage>Usage</h2>
|
||||
<ol>
|
||||
<li>Create your setup table. Remember that this pattern applies only to setup tables with a compound primary key;</li>
|
||||
<li>Create a function that will return the required value from the setup;</li>
|
||||
<li>For each level of specificity, the function should test if the corresponding record exists. If it does, the setup value should be returned. If it doesn’t, the logic should fall-back to a lower level of specificity.</li>
|
||||
<li>(Optional) If even the least specific setup record can not be found, the function may return a blank value or hard-coded default value.</li>
|
||||
</ol>
|
||||
<h2 id=nav-usages><strong>NAV Usages</strong></h2>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>The Printer Selection table in NAV is an example of the Setup Specificity Fallback pattern. Its primary key consists of two fields. A blank value in either field means that the record applies to any user or report respectively.</p>
|
||||
<p><a href=0724.Printer-Selection.png><img src=0724.Printer-Selection.png alt=" "></a></p>
|
||||
<p>The FindPrinter function in codeunit 1 searches for the printer to use, with a decreasing level of specificity.</p>
|
||||
|
|
@ -312,12 +323,12 @@ If found, return record; if not, optionally return hard-coded value</p>
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Silent File Upload and Download :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/silent-file-upload-and-download/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -279,13 +279,15 @@ ALGuidelines.Dev
|
|||
<p>Sometimes, files must be transferred to or from known locations without triggering file-save or file-load dialogs.</p>
|
||||
<p>In the following, both the historical and the recommended ways of silently transferring files are described. Since we keep both implementations possible for the sake of backward compatibility, we strongly recommend that you use the file-transfer API provided that is provided with the File Management codeunit (419).</p>
|
||||
<p>The legacy API for file transfers [2]:</p>
|
||||
<p>[Ok :=] UPLOAD(DialogTitle, FromFolder, FromFilter, FromFile, ToFile)</p>
|
||||
<p>[Ok :=] DOWNLOAD(FromFile, DialogTitle, ToFolder, ToFilter, ToFile)</p>
|
||||
<p>As you can see, this historical API leaves no place for turning off the functionality for showing a dialog. Historically, NAV offered a remedy to this, namely by using the “Magicpath” string, which is the constant ‘<TEMP>’. Under this condition, the way to invoke silent file upload or download becomes:</p>
|
||||
<p>[Ok :=] UPLOAD(DialogTitle, Magicpath, FromFilter, FromFile, ToFile)</p>
|
||||
<p>[Ok :=] DOWNLOAD(FromFile, DialogTitle, Magicpath, ToFilter, ToFile)</p>
|
||||
<p>This remedy introduced an issue: If we use “Magicpath” instead of <strong>FromFolder</strong> and <strong>ToFolder</strong> specifications, then where do we upload from and where do we download to? The answer is that they are uploaded to and downloaded from the NAV server’s temporary folder. The path to the temporary file can be obtained when this file is created, by using the following function in <strong>File Management: <tempFileName> := ServerTempFileName(<fileExtension>)</strong>.</p>
|
||||
<p>The new API for file transfers in the **File Management **codeunit:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[Ok <span style=color:#f92672>:=</span>] UPLOAD<span style=color:#f92672>(</span>DialogTitle, FromFolder, FromFilter, FromFile, ToFile<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>[Ok <span style=color:#f92672>:=</span>] DOWNLOAD<span style=color:#f92672>(</span>FromFile, DialogTitle, ToFolder, ToFilter, ToFile<span style=color:#f92672>)
|
||||
</span></code></pre></div><p>As you can see, this historical API leaves no place for turning off the functionality for showing a dialog. Historically, NAV offered a remedy to this, namely by using the “Magicpath” string, which is the constant ‘<TEMP>’. Under this condition, the way to invoke silent file upload or download becomes:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[Ok <span style=color:#f92672>:=</span>] UPLOAD<span style=color:#f92672>(</span>DialogTitle, Magicpath, FromFilter, FromFile, ToFile<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span>[Ok <span style=color:#f92672>:=</span>] DOWNLOAD<span style=color:#f92672>(</span>FromFile, DialogTitle, Magicpath, ToFilter, ToFile<span style=color:#f92672>)
|
||||
</span></code></pre></div><p>This remedy introduced an issue: If we use “Magicpath” instead of <strong>FromFolder</strong> and <strong>ToFolder</strong> specifications, then where do we upload from and where do we download to? The answer is that they are uploaded to and downloaded from the NAV server’s temporary folder. The path to the temporary file can be obtained when this file is created, by using the following function in <strong>File Management: <tempFileName> := ServerTempFileName(<fileExtension>)</strong>.</p>
|
||||
<p>The new API for file transfers in the <strong>File Management</strong> codeunit:</p>
|
||||
<p>[Text :=] UploadFileSilent(ClientFilePath)</p>
|
||||
<p>[Text :=] DownloadTempFile(ServerFileName)</p>
|
||||
<p>Using the API in the <strong>File Management</strong> codeunit instead of the historical API is recommended for all file transferring and file management in NAV implementations.</p>
|
||||
|
|
@ -297,15 +299,17 @@ ALGuidelines.Dev
|
|||
<p>The production manager wants to have the file in a predefined location on his hard drive. The location has been defined in a NAV setup table.</p>
|
||||
<h3 id=the-nav-developer>The NAV Developer</h3>
|
||||
<p>The NAV developer has written a module to query the CRONUS database and to export the product list in the pre-described XML format required by the web shop. He saves the data in a temporary server file created with this code:</p>
|
||||
<p>ServerFileName := FileManagement.ServerTempFileName(‘xml’);</p>
|
||||
<p>When the file has been populated with the latest product data, the NAV developer uses the following call to download the file from the temporary location on the server to the predefined location on the client:</p>
|
||||
<p>FileManagement.DownloadToFile(ServerFileName,ClientFileName);</p>
|
||||
<p>The call to <strong>DownloadToFile</strong> is part of the **File Management **codeunit, and it embeds the silent download offered by <strong>DownloadTempFile</strong>:</p>
|
||||
<p>PROCEDURE DownloadToFile@13(ServerFileName@1002 : Text;ClientFileName@1000 : Text);</p>
|
||||
<p>VAR TempClientFileName@1001 : Text;</p>
|
||||
<p>BEGIN ValidateFileNames(ServerFileName,ClientFileName); TempClientFileName := DownloadTempFile(ServerFileName); MoveFile(TempClientFileName,ClientFileName);</p>
|
||||
<p>END</p>
|
||||
<h2 id=consequences>Consequences</h2>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>ServerFileName <span style=color:#f92672>:=</span> FileManagement<span style=color:#f92672>.</span>ServerTempFileName<span style=color:#f92672>(</span><span style=color:#e6db74>'xml'</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>When the file has been populated with the latest product data, the NAV developer uses the following call to download the file from the temporary location on the server to the predefined location on the client:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>FileManagement<span style=color:#f92672>.</span>DownloadToFile<span style=color:#f92672>(</span>ServerFileName,ClientFileName<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>The call to <strong>DownloadToFile</strong> is part of the <strong>File Management</strong> codeunit, and it embeds the silent download offered by <strong>DownloadTempFile</strong>:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>PROCEDURE</span> DownloadToFile@<span style=color:#ae81ff>13</span><span style=color:#f92672>(</span>ServerFileName@<span style=color:#ae81ff>1002</span> : <span style=color:#66d9ef>Text</span>;ClientFileName@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Text</span><span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
TempClientFileName@<span style=color:#ae81ff>1001</span> : <span style=color:#66d9ef>Text</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
ValidateFileNames<span style=color:#f92672>(</span>ServerFileName,ClientFileName<span style=color:#f92672>)</span>; TempClientFileName <span style=color:#f92672>:=</span> DownloadTempFile<span style=color:#f92672>(</span>ServerFileName<span style=color:#f92672>)</span>; MoveFile<span style=color:#f92672>(</span>TempClientFileName,ClientFileName<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>
|
||||
</code></pre></div><h2 id=consequences>Consequences</h2>
|
||||
<ol>
|
||||
<li>Even today, there is no fully silent up or download. The user will get a warning stating the system is trying to run a client side .NET component. However when dismissing this warning, the user can show to not see it again.</li>
|
||||
<li>Due to client side .NET interop and of security concerns, silently downloading/uploading files on the web is disabled. Therefore, this pattern is recommended for implementation with Windows clients only.</li>
|
||||
|
|
@ -322,12 +326,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/singleton/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Singleton :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/singleton/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -264,7 +264,7 @@ ALGuidelines.Dev
|
|||
<li><strong>Lost reference to centralizer:</strong> An instance of a relevant object could attempt to centralize control or data in the system. However, once this object is no longer in scope, the reference to it is lost and cannot be retrieved for later coordination</li>
|
||||
<li><strong>Cannot rebuild the initial state:</strong> A new instance of the same object could be created, however the last known state of the lost instance cannot be known anymore.</li>
|
||||
</ul>
|
||||
<p><strong>Solution:</strong> create an object which resides in memory in a single copy (instance). Have a way to retrieve this unique object from code. This object can either be a <a href=/nav/w/designpatterns/151.singleton-table><strong>Singleton Table</strong></a>, or a <a href=/nav/w/designpatterns/283.singleton-codeunit><strong>Singleton Codeunit</strong></a>.</p>
|
||||
<p><strong>Solution:</strong> create an object which resides in memory in a single copy (instance). Have a way to retrieve this unique object from code. This object can either be a <a href=/navpatterns/1-patterns/singleton/singleton-table/><strong>Singleton Table</strong></a>, or a <a href=/navpatterns/1-patterns/singleton/singleton-codeunit/><strong>Singleton Codeunit</strong></a>.</p>
|
||||
<p>The implementation varies depending on the technology and language used. In object-oriented (OO) languages like C#, C++ or Java, the <strong>Singleton</strong> uses static classes and class members to instantiate. There is a mechanism to ensure only one instance of the object can exist. This mechanism is many times explicit (like in OO languages) and sometimes implicit as part of the compiler or platform (as it is in NAV).</p>
|
||||
<p><strong>Benefits:</strong></p>
|
||||
<ul>
|
||||
|
|
@ -284,12 +284,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Singleton on AL Guidelines</title><link>https://alguidelines.dev/navpatterns/1-patterns/singleton/</link><description>Recent content in Singleton on AL Guidelines</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://alguidelines.dev/navpatterns/1-patterns/singleton/index.xml" rel="self" type="application/rss+xml"/><item><title>Singleton Table</title><link>https://alguidelines.dev/navpatterns/1-patterns/singleton/singleton-table/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/singleton/singleton-table/</guid><description>Singleton Table By Elly Nkya at Microsoft Development Center Copenhagen
|
||||
_
|
||||
_
|
||||
Problem: The developer needs to define a single record that can contain a set of rules and behavior (optional, mandatory, or defaulting mechanisms), that apply to a functionality, and can be configured by a user.
|
||||
Forces
|
||||
You want a central place to define the address and logo of your company (see Company Information table). You want to define the no.</description></item><item><title>Singleton Codeunit</title><link>https://alguidelines.dev/navpatterns/1-patterns/singleton/singleton-codeunit/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/navpatterns/1-patterns/singleton/singleton-codeunit/</guid><description>By Bogdana Botez at Microsoft Development Center Copenhagen
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Singleton Codeunit :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/singleton/singleton-codeunit/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -267,25 +267,26 @@ ALGuidelines.Dev
|
|||
<p>Take for example the following test of Azure ML (Azure Machine Learning) integration with NAV.</p>
|
||||
<p>Context: Azure Machine Learning services are paid. However, Dynamics NAV includes a monthly pre-paid quota of Azure ML, which can be used for free by the users. There is an upper limit to this quota, and when it is reached, Azure ML services are turned off until the next month starts and a new quota becomes available for consumption.</p>
|
||||
<p>The test below checks that, when the monthly quota is exceeded, then the function IsAzureMLLimitReached returns TRUE.</p>
|
||||
<pre><code>\[Test\]
|
||||
PROCEDURE AzureMLProcessingTimeExceedsLimit@11();
|
||||
VAR
|
||||
AzureMachineLearningUsage@1004 : Record 2002;
|
||||
ProcessingTime@1000 : Decimal;
|
||||
BEGIN
|
||||
// \[SCENARIO\] Azure Machine Learning Processing time exceeds AzureML limit
|
||||
// \[GIVEN\] AzureMachineLearningUsage \> 0
|
||||
Initialize; // calls PermissionManager.SetTestabilitySoftwareAsAService(TRUE);
|
||||
ProcessingTime := LibraryRandom.RandDec(1000,2);
|
||||
AzureMachineLearningUsage.IncrementTotalProcessingTime(ProcessingTime);
|
||||
// \[WHEN\] When IsAzureMLLimitReached is invoked with Limit more than Processing time
|
||||
// \[THEN\] HasAzureLimitReached returns TRUE
|
||||
Assert.IsTrue(AzureMachineLearningUsage.IsAzureMLLimitReached(ProcessingTime - 1),
|
||||
'HasAzureLimitReached returns wrong value when Processing time exceeds Limit.');
|
||||
PermissionManager.SetTestabilitySoftwareAsAService(FALSE);
|
||||
END;
|
||||
</code></pre>
|
||||
<p>The figure below explains what happens when the Permission Manager is not a singleton. When it is invoked from different places (first from the test, second from the production code), then different instances of the Permission Manager will fire up and answer. In detail:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>[Test]
|
||||
<span style=color:#66d9ef>PROCEDURE</span> AzureMLProcessingTimeExceedsLimit@<span style=color:#ae81ff>11</span><span style=color:#f92672>()</span>;
|
||||
<span style=color:#66d9ef>VAR</span>
|
||||
AzureMachineLearningUsage@<span style=color:#ae81ff>1004</span> : <span style=color:#66d9ef>Record</span> <span style=color:#ae81ff>2002</span>;
|
||||
ProcessingTime@<span style=color:#ae81ff>1000</span> : <span style=color:#66d9ef>Decimal</span>;
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
<span style=color:#75715e>// [SCENARIO] Azure Machine Learning Processing time exceeds AzureML limit
|
||||
</span><span style=color:#75715e></span>
|
||||
<span style=color:#75715e>// [GIVEN] AzureMachineLearningUsage > 0
|
||||
</span><span style=color:#75715e></span> Initialize; <span style=color:#75715e>// calls PermissionManager.SetTestabilitySoftwareAsAService(TRUE);
|
||||
</span><span style=color:#75715e></span> ProcessingTime <span style=color:#f92672>:=</span> LibraryRandom<span style=color:#f92672>.</span>RandDec<span style=color:#f92672>(</span><span style=color:#ae81ff>1000</span>,<span style=color:#ae81ff>2</span><span style=color:#f92672>)</span>;
|
||||
AzureMachineLearningUsage<span style=color:#f92672>.</span>IncrementTotalProcessingTime<span style=color:#f92672>(</span>ProcessingTime<span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#75715e>// [WHEN] When IsAzureMLLimitReached is invoked with Limit more than Processing time
|
||||
</span><span style=color:#75715e></span> <span style=color:#75715e>// [THEN] HasAzureLimitReached returns TRUE
|
||||
</span><span style=color:#75715e></span> Assert<span style=color:#f92672>.</span>IsTrue<span style=color:#f92672>(</span>AzureMachineLearningUsage<span style=color:#f92672>.</span>IsAzureMLLimitReached<span style=color:#f92672>(</span>ProcessingTime - <span style=color:#ae81ff>1</span><span style=color:#f92672>)</span>,
|
||||
<span style=color:#e6db74>'HasAzureLimitReached returns wrong value when Processing time exceeds Limit.'</span><span style=color:#f92672>)</span>;
|
||||
PermissionManager<span style=color:#f92672>.</span>SetTestabilitySoftwareAsAService<span style=color:#f92672>(</span>FALSE<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>The figure below explains what happens when the Permission Manager is not a singleton. When it is invoked from different places (first from the test, second from the production code), then different instances of the Permission Manager will fire up and answer. In detail:</p>
|
||||
<ol>
|
||||
<li>The test calls Initialize which sets SaaS=TRUE in codeunit Permission Manager</li>
|
||||
<li>The test calls into production code to validate it works as expected. It calls AzureMachineLearningUsage codeunit to find out if the monthly quota has been reached. The function IsAzureMLLimitReached in AzureMachineLearningUsage codeunit is designed only for SaaS. If the code doesn’t run in SaaS, then it always returns FALSE.</li>
|
||||
|
|
@ -294,13 +295,11 @@ END;
|
|||
<li>The production code will assess (wrongly) that it’s not running SaaS, and say that the Azure ML limit has not been reached (incorrect – and the test fails).</li>
|
||||
</ol>
|
||||
<p><a href=Singleton-Codeunit-_2D00_-example-_2D00_-bad.PNG><img src=Singleton-Codeunit-_2D00_-example-_2D00_-bad.PNG alt=" "></a></p>
|
||||
<hr>
|
||||
<p><strong>Solution:</strong> restrict the number of instantiations of a codeunit to only one, by setting the codeunit property <strong>SingleInstance</strong> to <strong>Yes</strong>.</p>
|
||||
<p>Returning to the previous example, let’s analyze the case when the codeunit Permission Manager is a singleton codeunit:</p>
|
||||
<p><a href=2313.Singleton-Codeunit-_2D00_-CSIDE-SingleInstance-property.PNG><img src=2313.Singleton-Codeunit-_2D00_-CSIDE-SingleInstance-property.PNG alt=" "></a></p>
|
||||
<p>When the codeunit Permission Manager is a singleton, then no matter from where it is invoked, the same instance will be reached. Therefore, the status set by the test (SaaS = TRUE) will be reachable from the production code, and the test will pass, as seen in the figure below.</p>
|
||||
<p>**<a href=Singleton-Codeunit-_2D00_-example-_2D00_-good.PNG><img src=Singleton-Codeunit-_2D00_-example-_2D00_-good.PNG alt=" "></a><br>
|
||||
**</p>
|
||||
<p><a href=Singleton-Codeunit-_2D00_-example-_2D00_-good.PNG><img src=Singleton-Codeunit-_2D00_-example-_2D00_-good.PNG alt=" "></a></p>
|
||||
<p><strong>Consequences</strong></p>
|
||||
<p>1. Use Singleton Codeunit with care and only when there is no other solution. Preserving a global state could often enough be more harmful than useful. One risk is that tests might fail apparently non-deterministically.</p>
|
||||
<p>For example, a problem we have met in the development team for Madeira release, was that the singleton codeunit function PermissionManager.SetSoftwareAsAService(TRUE) is often used to emulate and test SaaS conditions. However, if a test ‘forgets’ to reset the state to default (FALSE), then another codeunit which is not supposed to emulate SaaS, will suddenly run as SaaS and will fail. Even if the test has code that resets the state to FALSE, this code might never be reached because of an earlier failure or other error in the test which would stop execution.</p>
|
||||
|
|
@ -318,7 +317,6 @@ END;
|
|||
<li>Etc.</li>
|
||||
</ul>
|
||||
<p><strong>Note:</strong> while the object-oriented <strong>Singleton</strong> pattern can restrict the number of instantiations of the singleton to an integer n > 0, in Dynamics NAV the <strong>Singleton Codeunit</strong> can only have n=1.</p>
|
||||
<p>__</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -331,12 +329,12 @@ END;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Cue Table :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/singleton/singleton-table/cue-table/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -258,72 +258,112 @@ ALGuidelines.Dev
|
|||
<h1>Cue Table</h1>
|
||||
<p><em>By Bogdana Botez at Microsoft Development Center Copenhagen</em></p>
|
||||
<p><a href=Cue-Table.png><img src=Cue-Table.png alt=" "></a></p>
|
||||
<p>Cues are the second usual application of the <a href=/nav/w/designpatterns/151.singleton-table><strong>Singleton Table</strong></a> pattern in Dynamics NAV, after <a href=/nav/w/designpatterns/76.setup-table><strong>Setup Tables</strong></a>.</p>
|
||||
<p>Cues are the second usual application of the <a href=/navpatterns/1-patterns/singleton/singleton-table/><strong>Singleton Table</strong></a> pattern in Dynamics NAV, after <a href=/navpatterns/1-patterns/singleton/singleton-table/setup-table/><strong>Setup Tables</strong></a>.</p>
|
||||
<p><strong>Context</strong>: The user gets overview information about the business on the Dynamics NAV Role Center page.</p>
|
||||
<p>Figure 1 - Cue information in Dynamics NAV shows cue information seen by the user on the <strong>Sales Order Processor</strong> role center.</p>
|
||||
<p><a href=Cue-Table-Figure-1.JPG><img src=Cue-Table-Figure-1.JPG alt=" "></a></p>
|
||||
<p>The overview information consists of summed-up numbers, calculated from business data, like for example how many sales orders are still open, how many shipments are ready to go, or partially shipped, how many documents are waiting for approval etc.</p>
|
||||
<p><strong>Problem</strong>: 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.</p>
|
||||
<p><strong>Solution:</strong> Store overview information in a singleton table.</p>
|
||||
<hr>
|
||||
<p>There are two ways of calculating overview information in NAV.</p>
|
||||
<ol>
|
||||
<li>By using a FlowField. This applies for simpler calculations, like filtered or unfiltered counts, sums etc.</li>
|
||||
<li>By writing C/AL code to perform custom calculations. Use this when:</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>
|
||||
<p>By using a FlowField. This applies for simpler calculations, like filtered or unfiltered counts, sums etc.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>By writing C/AL code to perform custom calculations. Use this when:</p>
|
||||
<ul>
|
||||
<li>The way to calculate the overview is too complex for flow fields, or</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>The data needs to be pulled from an external system (like Dynamics CRM, QuickBooks or any external integration).</li>
|
||||
</ul>
|
||||
<hr>
|
||||
</li>
|
||||
</ol>
|
||||
<p>The implementation of Cues is already described in detail on MSDN, in <a href="https://msdn.microsoft.com/en-us/library/dn789553(v=nav.90).aspx">Creating and Customizing Cues</a> and in <a href="https://msdn.microsoft.com/en-us/library/ff477101(v=nav.90).aspx">Walkthrough: Creating a Cue Based on a FlowField</a>.</p>
|
||||
<p><strong>NAV Usages</strong></p>
|
||||
<p><em>Table 1 - Cue tables in Dynamics NAV</em> shows some examples of singleton tables used for creating Cues.</p>
|
||||
<p>Table ID</p>
|
||||
<p>Table Name</p>
|
||||
<p>1313</p>
|
||||
<p>Activities Cue</p>
|
||||
<p>5370</p>
|
||||
<p>CRM Synch. Job Status Cue</p>
|
||||
<p>9042</p>
|
||||
<p>Team Member Cue</p>
|
||||
<p>9050</p>
|
||||
<p>Warehouse Basic Cue</p>
|
||||
<p>9051</p>
|
||||
<p>Warehouse WMS Cue</p>
|
||||
<p>9052</p>
|
||||
<p>Service Cue</p>
|
||||
<p>9053</p>
|
||||
<p>Sales Cue</p>
|
||||
<p>9054</p>
|
||||
<p>Finance Cue</p>
|
||||
<p>9055</p>
|
||||
<p>Purchase Cue</p>
|
||||
<p>9056</p>
|
||||
<p>Manufacturing Cue</p>
|
||||
<p>9057</p>
|
||||
<p>Job Cue</p>
|
||||
<p>9058</p>
|
||||
<p>Warehouse Worker WMS Cue</p>
|
||||
<p>9059</p>
|
||||
<p>Administration Cue</p>
|
||||
<p>9060</p>
|
||||
<p>SB Owner Cue</p>
|
||||
<p>9061</p>
|
||||
<p>RapidStart Services Cue</p>
|
||||
<p>9063</p>
|
||||
<p>Relationship Mgmt. Cue</p>
|
||||
<p>9069</p>
|
||||
<p>O365 Sales Cue</p>
|
||||
<p>9070</p>
|
||||
<p>Accounting Services Cue</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Table ID</th>
|
||||
<th>Table Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1313</td>
|
||||
<td>Activities Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5370</td>
|
||||
<td>CRM Synch. Job Status Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9042</td>
|
||||
<td>Team Member Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9050</td>
|
||||
<td>Warehouse Basic Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9051</td>
|
||||
<td>Warehouse WMS Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9052</td>
|
||||
<td>Service Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9053</td>
|
||||
<td>Sales Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9054</td>
|
||||
<td>Finance Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9055</td>
|
||||
<td>Purchase Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9056</td>
|
||||
<td>Manufacturing Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9057</td>
|
||||
<td>Job Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9058</td>
|
||||
<td>Warehouse Worker WMS Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9059</td>
|
||||
<td>Administration Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9060</td>
|
||||
<td>SB Owner Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9061</td>
|
||||
<td>RapidStart Services Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9063</td>
|
||||
<td>Relationship Mgmt. Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9069</td>
|
||||
<td>O365 Sales Cue</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9070</td>
|
||||
<td>Accounting Services Cue</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Table 1 - Cue tables in Dynamics NAV</p>
|
||||
<hr>
|
||||
<p>_</p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -336,12 +376,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
<link rel=alternate type=application/rss+xml href=/navpatterns/1-patterns/singleton/singleton-table/index.xml title="AL Guidelines">
|
||||
<meta name=description content>
|
||||
<title>Singleton Table :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506471 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506471 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506471></script>
|
||||
<link href=/css/nucleus.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600601 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600601 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600601></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/singleton/singleton-table/>
|
||||
|
|
@ -33,9 +33,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506471></script>
|
||||
<script src=/js/auto-complete.js?1644506471></script>
|
||||
<script src=/js/search.js?1644506471></script>
|
||||
<script src=/js/lunr.min.js?1644600601></script>
|
||||
<script src=/js/auto-complete.js?1644600601></script>
|
||||
<script src=/js/search.js?1644600601></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -251,7 +251,6 @@ ALGuidelines.Dev
|
|||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#singleton-table>Singleton Table</a></li>
|
||||
<li><a href=#-image0anchor0><a href=5554.Singleton-Table.png><img src=5554.Singleton-Table.png alt=" "></a></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -263,11 +262,8 @@ ALGuidelines.Dev
|
|||
<h1>Singleton Table</h1>
|
||||
<h2 id=singleton-table>Singleton Table</h2>
|
||||
<p><em>By Elly Nkya at Microsoft Development Center Copenhagen</em></p>
|
||||
<h2 id=-image0anchor0><a href=5554.Singleton-Table.png><img src=5554.Singleton-Table.png alt=" "></a></h2>
|
||||
<p>_<br>
|
||||
_</p>
|
||||
<p><a href=5554.Singleton-Table.png><img src=5554.Singleton-Table.png alt=" "></a></p>
|
||||
<p><strong>Problem</strong>: The developer needs to define a single record that can contain a set of rules and behavior (optional, mandatory, or defaulting mechanisms), that apply to a functionality, and can be configured by a user.</p>
|
||||
<hr>
|
||||
<p><strong>Forces</strong></p>
|
||||
<ul>
|
||||
<li>You want a central place to define the address and logo of your company (see Company Information table).</li>
|
||||
|
|
@ -282,43 +278,38 @@ _</p>
|
|||
<p><strong>2. Instantiate:</strong> Place the instantiation code in a central place where it is guaranteed to be invoked before the functionality uses it. This is done in Codeunit 2.</p>
|
||||
<p><strong>3. Enforce:</strong> Give the user access to the record so that he can change the default setup, by creating a Card page. On the page, enforce the singleton to prevent deletion of the record or insertion of a new record</p>
|
||||
<p><strong>4. Use:</strong> Access the rule in code and use it</p>
|
||||
<hr>
|
||||
<p><strong>NAV Usages</strong></p>
|
||||
<p>Rounding rules for Unit-Amounts and Amounts are implemented using the Singleton pattern.</p>
|
||||
<p><strong>1. Define:</strong> The General Ledger Setup is used for this.</p>
|
||||
<p><strong>2. Instantiate:</strong> In codeunit 2, the following code is invoked</p>
|
||||
<pre><code>WITH GLSetup DO
|
||||
IF NOT FINDFIRST THEN BEGIN
|
||||
INIT;
|
||||
INSERT;
|
||||
END;
|
||||
</code></pre>
|
||||
<p><strong>3. Enforce:</strong> On the General Ledger Setup. The following properties are setup:</p>
|
||||
<pre><code>DeleteAllowed=false,
|
||||
InsertAllowed=false
|
||||
</code></pre>
|
||||
<p><strong>4. Use:</strong> Access the rounding rules are used</p>
|
||||
<pre><code>...
|
||||
GLSetup.GET;
|
||||
UnitCostCurrency := ROUND(...,GLSetup."Unit-Amount Rounding Precision");
|
||||
...
|
||||
</code></pre>
|
||||
<p>Or if accessing the rule multiple times and performance is a consideration, use lazy instantiation:</p>
|
||||
<pre><code>...
|
||||
GetGLSetup;
|
||||
UnitCostCurrency := ROUND(...,GLSetup."Unit-Amount Rounding Precision");
|
||||
...
|
||||
|
||||
LOCAL GetGLSetup()
|
||||
IF NOT GLSetupRead THEN
|
||||
GLSetup.GET;
|
||||
GLSetupRead := TRUE;
|
||||
</code></pre>
|
||||
<p><strong>Related topics</strong></p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>WITH</span> GLSetup <span style=color:#66d9ef>DO</span>
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> FINDFIRST <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
INIT;
|
||||
INSERT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p><strong>3. Enforce:</strong> On the General Ledger Setup. The following properties are setup:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al> DeleteAllowed=false,
|
||||
InsertAllowed=false
|
||||
</code></pre></div><p><strong>4. Use:</strong> Access the rounding rules are used</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#f92672>...
|
||||
</span><span style=color:#f92672></span>GLSetup<span style=color:#f92672>.</span>GET;
|
||||
UnitCostCurrency <span style=color:#f92672>:=</span> ROUND<span style=color:#f92672>(...</span>,GLSetup<span style=color:#f92672>.</span>"Unit-Amount Rounding Precision"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#f92672>...
|
||||
</span></code></pre></div><p>Or if accessing the rule multiple times and performance is a consideration, use lazy instantiation:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#f92672>...
|
||||
</span><span style=color:#f92672></span>GetGLSetup;
|
||||
UnitCostCurrency <span style=color:#f92672>:=</span> ROUND<span style=color:#f92672>(...</span>,GLSetup<span style=color:#f92672>.</span>"Unit-Amount Rounding Precision"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#f92672>...
|
||||
</span><span style=color:#f92672>
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>LOCAL</span> GetGLSetup<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672></span><span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> GLSetupRead <span style=color:#66d9ef>THEN</span>
|
||||
GLSetup<span style=color:#f92672>.</span>GET;
|
||||
GLSetupRead <span style=color:#f92672>:=</span> TRUE;
|
||||
</code></pre></div><p><strong>Related topics</strong></p>
|
||||
<p><a href=https://en.wikipedia.org/wiki/Singleton_pattern>Singleton design pattern</a>.</p>
|
||||
<p>The <strong>Singleton Table</strong> has two established applications in Dynamics NAV:</p>
|
||||
<ol>
|
||||
<li><a href=/nav/w/designpatterns/76.setup-table><strong>Setup Tables</strong></a> – which are commonly storing user setup data in NAV,</li>
|
||||
<li><a href=/navpatterns/1-patterns/singleton/singleton-table/setup-table/><strong>Setup Tables</strong></a> – which are commonly storing user setup data in NAV,</li>
|
||||
<li><strong>Cue Tables</strong> – used to calculate values for the visual representation of Cues on the NAV role center pages.</li>
|
||||
</ol>
|
||||
<p>YouTube Video of NAV Singleton:</p>
|
||||
|
|
@ -337,12 +328,12 @@ GLSetupRead := TRUE;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506471></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506471></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506471></script>
|
||||
<script src=/js/featherlight.min.js?1644506471></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506471></script>
|
||||
<script src=/js/relearn.js?1644506471></script>
|
||||
<script src=/js/clipboard.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600601></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600601></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600601></script>
|
||||
<script src=/js/featherlight.min.js?1644600601></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600601></script>
|
||||
<script src=/js/relearn.js?1644600601></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Setup Table :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600600 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600600 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600600></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/singleton/singleton-table/setup-table/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600600></script>
|
||||
<script src=/js/auto-complete.js?1644600600></script>
|
||||
<script src=/js/search.js?1644600600></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -274,14 +274,13 @@ ALGuidelines.Dev
|
|||
<p><strong>Creating a Page</strong></p>
|
||||
<p>The <strong>CardPage</strong> type is most suitable for representing this kind of tables. In addition, the <strong>InsertAllowed</strong> and <strong>DeleteAllowed</strong> properties in the page should be set to false to prevent the user from adding or deleting records in the table.</p>
|
||||
<p>In the <strong>OnOpenPage</strong> trigger, the following code should be added to insert a record when the user opens the page for the first time, if a record does not exist already.</p>
|
||||
<pre><code>OnOpenPage()
|
||||
RESET;
|
||||
IF NOT GET THEN BEGIN
|
||||
INIT;
|
||||
INSERT;
|
||||
END;
|
||||
</code></pre>
|
||||
<p>The following diagram describes the flow of the program, once the user tries to access the setup information. The user opens the page. If the record containing setup information already exists, then the page opens on the existing record. Else, a new empty record is created and the page opens on it.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>OnOpenPage<span style=color:#f92672>()
|
||||
</span><span style=color:#f92672> </span>RESET;
|
||||
<span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> GET <span style=color:#66d9ef>THEN</span> <span style=color:#66d9ef>BEGIN</span>
|
||||
INIT;
|
||||
INSERT;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>The following diagram describes the flow of the program, once the user tries to access the setup information. The user opens the page. If the record containing setup information already exists, then the page opens on the existing record. Else, a new empty record is created and the page opens on it.</p>
|
||||
<p><a href=6675.NAVSetupTablePattern2.png><img src=6675.NAVSetupTablePattern2.png alt=" "></a></p>
|
||||
<p><strong>Company-Initialize Codeunit</strong></p>
|
||||
<p>The Company-Initialize codeunit (codeunit 2) is executed when a new company is created. We recommended that you add records to the single-record tables in this codeunit. If some of the fields are expected to have default values, they can also be populated here.</p>
|
||||
|
|
@ -308,12 +307,12 @@ END;
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600600></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600600></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600600></script>
|
||||
<script src=/js/featherlight.min.js?1644600600></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600600></script>
|
||||
<script src=/js/relearn.js?1644600600></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Standard Journal :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/standard-journal/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -314,12 +314,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Temporary Dataset Report :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/temporary-dataset-report/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -250,7 +250,11 @@ ALGuidelines.Dev
|
|||
<ul>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#description>Description</a></li>
|
||||
<li><a href=#usage>Usage</a></li>
|
||||
<li><a href=#usage>Usage</a>
|
||||
<ul>
|
||||
<li></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href=#example>Example</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -264,7 +268,7 @@ ALGuidelines.Dev
|
|||
<p><em>Originally by Abhishek Ghosh, at Microsoft Development Center Copenhagen</em></p>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>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.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/0250.Temporary-Dataset-Report-1.gif><img src=/resized-image.ashx/__size/550x0/__key/communityserver-wikis-components-files/00-00-00-00-42/0250.Temporary-Dataset-Report-1.gif alt=" "></a><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/8424.Temporary-Dataset-Report-1.gif></a></p>
|
||||
<p><a href=0250.Temporary-Dataset-Report-1.png><img src=0250.Temporary-Dataset-Report-1.png alt=" "></a></p>
|
||||
<h2 id=description>Description</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
|
|
@ -278,23 +282,37 @@ ALGuidelines.Dev
|
|||
<p>Iterate through a dataitem of the Integer table and display one record from the temporary recordset in each iteration.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Step 1: Combining data sources to create a dataset</p>
|
||||
<h4 id=step-1-combining-data-sources-to-create-a-dataset>Step 1: Combining data sources to create a dataset</h4>
|
||||
<p>In this step, we would process the existing data to create a temporary recordset. The three most common techniques to do this are discussed in the following paragraphs.</p>
|
||||
<p>The first technique is mostly used when we want to build the report based on one or more source tables. A lot of processing is required, and we therefore want to store and display information from a temporary recordset. With this technique, we create a dataitem of the source record and then iterate through this dataitem to create the temporary recordset. An advantage of this technique is that it allows the user to perform additional filtering on the data source tables since they are added as additional dataitems and therefore will have their tabs on the request page by default.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/2376.Temporary-Dataset-Report-2.gif><img src=/resized-image.ashx/__size/550x0/__key/communityserver-wikis-components-files/00-00-00-00-42/2376.Temporary-Dataset-Report-2.gif alt=" "></a><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/8461.Temporary-Dataset-Report-2.gif></a></p>
|
||||
<p><a href=2376.Temporary-Dataset-Report-2.png><img src=2376.Temporary-Dataset-Report-2.png alt=" "></a></p>
|
||||
<p>The second technique was made available with NAV 2013 when queries were introduced as a tool to help us combine data from different sources. Instead of writing data into a temporary record variable, we can create a query to combine the data from different sources. This offers better performance than the first technique in almost every situation. However, with a query, we sacrifice the luxury of getting a flexible filtering on the request page for the source dataitem.</p>
|
||||
<p>The third technique is to write a function (or a codeunit, if the complexity demands so) that will crunch the data and create the temporary record variable. This function must be invoked from the OnPreReport trigger (or the OnPreDataItem trigger of the Integer dataitem).</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/7607.Temporary-Dataset-Report-3.gif><img src=/resized-image.ashx/__size/550x0/__key/communityserver-wikis-components-files/00-00-00-00-42/7607.Temporary-Dataset-Report-3.gif alt=" "></a></p>
|
||||
<p><a href=7607.Temporary-Dataset-Report-3.png><img src=7607.Temporary-Dataset-Report-3.png alt=" "></a></p>
|
||||
<p>The following table summarizes when to use each of the three techniques:</p>
|
||||
<p>Technique</p>
|
||||
<p>When to Use</p>
|
||||
<p>Source Record DataItem</p>
|
||||
<p>When it is important to offer flexible filtering possibilities on the source data.</p>
|
||||
<p>Query</p>
|
||||
<p>When performance is critical.</p>
|
||||
<p>Populating temporary table in a function</p>
|
||||
<p>Only when the source dataset is too complex to use either of the other techniques.</p>
|
||||
<p>Step 2: Iterating through the Integer dataitem</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Technique</th>
|
||||
<th>When to Use</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Source Record DataItem</td>
|
||||
<td>When it is important to offer flexible filtering possibilities on the source data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Query</td>
|
||||
<td>When performance is critical.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Populating temporary table in a function</td>
|
||||
<td>Only when the source dataset is too complex to use either of the other techniques.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4 id=step-2-iterating-through-the-integer-dataitem>Step 2: Iterating through the Integer dataitem</h4>
|
||||
<p>When you have created the dataset as a temporary record variable or a query, the next step is to iterate through them to display the information. However, the report controller in NAV cannot iterate through temporary records or through the results of a query. This is where the Integer table comes into use.</p>
|
||||
<p>The Integer table is a virtual table with only one field, Number, which is an integer field. For all practical purposes, we can assume that this table has pre-inserted records with value of Number, starting from 1 and ending with the highest integer value. So, if we keep iterating through this dataitem, the value of the Number field will be 1 for the first iteration and will keep increasing by 1 for every iteration.</p>
|
||||
<p>There are two ways to use the Integer dataitem to iterate through the temporary recordset:</p>
|
||||
|
|
@ -309,9 +327,9 @@ ALGuidelines.Dev
|
|||
<p>With the first approach, in the Integer-OnAfterGetRecord trigger, you must make the temporary record variable move to the next record, follow that up with a check if you have reached the end of the recordset, and then use CurrReport.BREAK if you have reached the end.</p>
|
||||
<p>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.</p>
|
||||
<h2 id=example>Example</h2>
|
||||
<p>Goal: To print a report that lists all contacts that have open documents (both sales and purchase) and displays those documents in chronological order</p>
|
||||
<p><strong>Goal:</strong> To print a report that lists all contacts that have open documents (both sales and purchase) and displays those documents in chronological order</p>
|
||||
<p>A contact can be connected to a vendor or a customer using the Create As Customer/Vendor function on the Contact Card. When a sales/purchase document is created for this customer/vendor, the Contact No. is stored in the Sell-to Contact No. or Buy-from Contact No. fields of the sales and purchase documents. The obvious choice would be to display the data directly from the Sales Header and Purchase Header records. However, the requirement is to display all of them together chronologically, which means they will need to be stored in, and be read from, one common dataset.</p>
|
||||
<p>Step 1: Design a new table that will hold the temporary dataset.</p>
|
||||
<p><strong>Step 1: Design a new table that will hold the temporary dataset.</strong></p>
|
||||
<p>The UI must display the Document Type, Document No., Document Date, Amount Incl. VAT and the name of the salesperson or purchaser. The table is designed as follows.</p>
|
||||
<p><a href=6523.Temporary-Dataset-Report-4.jpg><img src=6523.Temporary-Dataset-Report-4.jpg alt=" "></a></p>
|
||||
<p>Since this table is used to sort the data by Document Date, a “Document Date” key is added to the table.</p>
|
||||
|
|
@ -325,9 +343,9 @@ ALGuidelines.Dev
|
|||
<p>Purchase Header dataitem should be linked to the Contact dataitem through the DataItemLink property – “Buy-from Contact No.=FIELD(No.)”</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Step 2: In the Sales Header – OnAfterGetRecord, write the following code to populate the data buffer:</p>
|
||||
<p><strong>Step 2: In the Sales Header</strong> – OnAfterGetRecord, write the following code to populate the data buffer:</p>
|
||||
<p><a href=4010.Temporary-Dataset-Report-6.jpg><img src=4010.Temporary-Dataset-Report-6.jpg alt=" "></a></p>
|
||||
<p>Where:</p>
|
||||
<p><strong>Where:</strong></p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>ContactDocumentBuffer is a temporary global variable of the buffer table created.</p>
|
||||
|
|
@ -340,17 +358,18 @@ ALGuidelines.Dev
|
|||
</li>
|
||||
</ul>
|
||||
<p>Similar code must be written in Purchase Header – OnAfterGetRecord to store data from the purchase documents into the buffer.</p>
|
||||
<p>Step 3: Iterate through the temporary records in the Integer dataitem.</p>
|
||||
<p><strong>Step 3:</strong> Iterate through the temporary records in the Integer dataitem.</p>
|
||||
<p>Since the requirement is to sort the data by Document Date, we must sort the ContactDocumentBuffer table by this key. Also, by the time the execution of Integer – OnPreDataItem begins, the number of records in the temporary buffer should be known already. Therefore, we can limit the number of times to repeat the Integer dataitem to the number of records in the buffer.</p>
|
||||
<p>We meet both requirements with the following lines of code in Integer - OnPreDataItem:</p>
|
||||
<p>ContactDocumentBuffer.SETCURRENTKEY(“Document Date”);</p>
|
||||
<p>SETRANGE(Number,1,ContactDocumentBuffer.COUNT);</p>
|
||||
<p>Lastly, we must move the record pointer by 1 record every time we loop through the Integer dataitem. So, in Integer – OnAfterGetRecord, we add the following lines of code:</p>
|
||||
<p>IF Number = 1 THEN</p>
|
||||
<p>ContactDocumentBuffer.FINDFIRST</p>
|
||||
<p>ELSE</p>
|
||||
<p>ContactDocumentBuffer.NEXT;</p>
|
||||
<p>Now, the only task that remains is to design the RDLC layout. (Not part of this application pattern description.)</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>ContactDocumentBuffer<span style=color:#f92672>.</span>SETCURRENTKEY<span style=color:#f92672>(</span>"Document Date"<span style=color:#f92672>)</span>;
|
||||
|
||||
SETRANGE<span style=color:#f92672>(</span>Number,<span style=color:#ae81ff>1</span>,ContactDocumentBuffer<span style=color:#f92672>.</span><span style=color:#66d9ef>COUNT</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Lastly, we must move the record pointer by 1 record every time we loop through the Integer dataitem. So, in Integer – OnAfterGetRecord, we add the following lines of code:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> Number = <span style=color:#ae81ff>1</span> <span style=color:#66d9ef>THEN</span>
|
||||
ContactDocumentBuffer<span style=color:#f92672>.</span>FINDFIRST
|
||||
<span style=color:#66d9ef>ELSE</span>
|
||||
ContactDocumentBuffer<span style=color:#f92672>.</span>NEXT;
|
||||
</code></pre></div><p>Now, the only task that remains is to design the RDLC layout. (Not part of this application pattern description.)</p>
|
||||
<p>NAV Usages</p>
|
||||
<p>This is a commonly used pattern in several reports, such as:</p>
|
||||
<ul>
|
||||
|
|
@ -379,12 +398,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Totals and Discounts on Subpages Sales and Purchases :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/totals-and-discounts-on-subpages-sales-and-purchases/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -364,15 +364,14 @@ ALGuidelines.Dev
|
|||
<p>After Platform added support for this specific case, the layout is very simple, as follows.</p>
|
||||
<p><a href=Fig-10.jpg><img src=Fig-10.jpg alt=" "></a></p>
|
||||
<p>This will produce the layout we wanted:</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/Fig-11.jpg><img src=/resized-image.ashx/__size/550x0/__key/communityserver-wikis-components-files/00-00-00-00-42/Fig-11.jpg alt=" "></a></p>
|
||||
<p><a href=Fig-11.jpg><img src=Fig-11.jpg alt=" "></a></p>
|
||||
<h3 id=ui----manual-totals-update>UI – Manual Totals Update</h3>
|
||||
<p>As mentioned before, there are cases when the user is informed that totals/discounts might not be up to date and that it should select a link in order to get the updated values.</p>
|
||||
<p>The link is part of the sub-part where totals and discounts are added. The visibility is controlled by actually controlling the text (message, or empty), because Platform does not support making only one visible/invisible (it must be a group). When the link is displayed, the styling is also changed for the total/discount controls, and the values are set to 0.</p>
|
||||
<p><a href=/cfs-file.ashx/__key/communityserver-wikis-components-files/00-00-00-00-42/Fig-12.jpg><img src=/resized-image.ashx/__size/550x0/__key/communityserver-wikis-components-files/00-00-00-00-42/Fig-12.jpg alt=" "></a></p>
|
||||
<p><a href=Fig-12.jpg><img src=Fig-12.jpg alt=" "></a></p>
|
||||
<h2 id=nav-usages>NAV Usages</h2>
|
||||
<p>We have implemented these scenarios for sales and purchase documents (order, invoice, quote, credit memos, return orders, including posted documents). Note that the implementation in NAV 2015 is a bit different than the one in NAV 2014 C5 objects (1300 range). It was decided not to merge the two implementations, among other reasons because the NAV 2014 C5 implementation does not fit the full application.</p>
|
||||
<p>The pattern can easily be extended to new sales and purchase documents. If the pattern is followed, it can also be extended to other types of documents, such as in services, jobs, etc.</p>
|
||||
<hr>
|
||||
<p><strong>Note:</strong> This new pattern is not implemented in the North America and India versions. This is due to special local features in the two versions regions and the multitude of sales tax/vat options that would make the solution non-user friendly and not optimized for performance.</p>
|
||||
<h2 id=ideas-for-improvement>Ideas for Improvement</h2>
|
||||
<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.</p>
|
||||
|
|
@ -391,12 +390,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Transfer Custom Fields :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/transfer-custom-fields/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -269,12 +269,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,16 @@
|
|||
<meta name=generator content="Hugo 0.92.1">
|
||||
<meta name=description content>
|
||||
<title>Variant Facade :: AL Guidelines</title>
|
||||
<link href=/css/nucleus.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644506469 rel=stylesheet>
|
||||
<link href=/css/print.css?1644506469 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644506469></script>
|
||||
<link href=/css/nucleus.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/fontawesome-all.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/featherlight.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/perfect-scrollbar.min.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/auto-complete.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/theme-blue.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/variant.css?1644600599 rel=stylesheet>
|
||||
<link href=/css/print.css?1644600599 rel=stylesheet media=print>
|
||||
<script src=/js/jquery.min.js?1644600599></script>
|
||||
<style>:root #header+#content>#left>#rlblock_left{display:none!important}</style>
|
||||
</head>
|
||||
<body data-url=/navpatterns/1-patterns/variant-facade/>
|
||||
|
|
@ -32,9 +32,9 @@ ALGuidelines.Dev
|
|||
<input data-search-input id=search-by type=search placeholder=Search...>
|
||||
<span data-search-clear><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<script src=/js/lunr.min.js?1644506469></script>
|
||||
<script src=/js/auto-complete.js?1644506469></script>
|
||||
<script src=/js/search.js?1644506469></script>
|
||||
<script src=/js/lunr.min.js?1644600599></script>
|
||||
<script src=/js/auto-complete.js?1644600599></script>
|
||||
<script src=/js/search.js?1644600599></script>
|
||||
</div>
|
||||
<div class=highlightable>
|
||||
<ul class=topics>
|
||||
|
|
@ -248,11 +248,21 @@ ALGuidelines.Dev
|
|||
<div class=wrapper>
|
||||
<nav id=TableOfContents>
|
||||
<ul>
|
||||
<li><a href=#abstract>Abstract</a></li>
|
||||
<li><a href=#problem>Problem</a></li>
|
||||
<li><a href=#solution>Solution</a>
|
||||
<ul>
|
||||
<li><a href=#signature>Signature</a></li>
|
||||
<li><a href=#casting-to-a-record-ref>Casting to a record ref</a></li>
|
||||
<li><a href=#using-the-variant>Using the variant</a></li>
|
||||
<li><a href=#table-specific-code>Table specific code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href=#example>Example</a></li>
|
||||
<li><a href=#consequences>Consequences</a></li>
|
||||
<li><a href=#nav-usages>NAV usages</a></li>
|
||||
<li><a href=#related-topics>Related Topics</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -262,11 +272,10 @@ ALGuidelines.Dev
|
|||
<main id=body-inner>
|
||||
<h1>Variant Facade</h1>
|
||||
<p><em>By Nikola Kukrika, waldo and Gary Winter</em></p>
|
||||
<h1 id=abstract>Abstract</h1>
|
||||
<h2 id=abstract>Abstract</h2>
|
||||
<p>The Variant façade provides a single interface that can take any Record, RecordRef or RecordID as an argument. With this pattern the code is encapsulated within the single object, with clear separation between common and table specific code.</p>
|
||||
<p><a href=picture1.png><img src=picture1.png alt=" "></a></p>
|
||||
<hr>
|
||||
<h1 id=problem>Problem</h1>
|
||||
<h2 id=problem>Problem</h2>
|
||||
<p>Since NAV is strongly typed, developers often need to duplicate functionality in order to add support for a new table. The developer would typically start by duplicating the function, changing the record type and implement slight modifications to the code if needed.</p>
|
||||
<p>The problem with this approach is that code duplication is one of the worst things in software development – it makes code harder to understand, maintain, extend and test.</p>
|
||||
<p>One of the good examples of this approach and the resulting duplication is codeunit 229, Document-Print:</p>
|
||||
|
|
@ -285,15 +294,15 @@ ALGuidelines.Dev
|
|||
<p><strong>Testing the code</strong> is hard since the tests need to be replicated.</p>
|
||||
<p><strong>Constant cost of adding support for new tables</strong> – 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.</p>
|
||||
<p><strong>Conclusion</strong> - <strong>If the functionality needs to be used for many records the approach of duplicating the functions should be avoided.</strong></p>
|
||||
<h1 id=solution>Solution</h1>
|
||||
<h2 id=solution>Solution</h2>
|
||||
<p>The Variant façade pattern provides a single interface that would not need to be changed in the future. It will be able to take any record as a parameter. Common code should be kept separately from record specific code and both must be very visible so the developers can easily see what the differences are.</p>
|
||||
<p>The Key components of the pattern are:</p>
|
||||
<h2 id=signature>Signature</h2>
|
||||
<h3 id=signature>Signature</h3>
|
||||
<p>Instead of hardcoding a record type a variant is used as an argument. A Variant Façade function can receive three types of data: Record, RecordID, or RecordRef. This way, it can be reused anywhere in the product and the code will still work.</p>
|
||||
<p>A good practice is to combine this pattern with the Argument Table pattern to make sure that the signature does not change (Additional parameters can be added to the argument table without impacting existing code.). If the Argument Table is not needed, it should not be placed in the signature - it is always possible to add it at a latter point and have two public functions (one with and one without arguments).</p>
|
||||
<p>Example - For codeunit 229, Document-Print all of the public methods can be simply replaced with a single public method like this:</p>
|
||||
<p>With this approach the façade function can serve all of the record types and will not need to change in the future.</p>
|
||||
<h2 id=casting-to-a-record-ref>Casting to a record ref</h2>
|
||||
<h3 id=casting-to-a-record-ref>Casting to a record ref</h3>
|
||||
<p>After the signature it is necessary to decide if the function will support passing of the Record ID and the RecordRef. Code tends to be easier to understand and maintain if only the records are passed as the arguments, however in some cases it is needed to support the other two types.</p>
|
||||
<ul>
|
||||
<li><strong>Support for Record, Record ID and RecordRef:</strong></li>
|
||||
|
|
@ -303,93 +312,98 @@ ALGuidelines.Dev
|
|||
<ul>
|
||||
<li><strong>Support Records only</strong> - If the function supports only passing in the record, it is a good practice to check if the variant is a record:</li>
|
||||
</ul>
|
||||
<p>IF NOT RecordVariant.ISRECORD THEN</p>
|
||||
<p>ERROR(NotARecordErr);</p>
|
||||
<h2 id=using-the-variant>Using the variant</h2>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>IF</span> <span style=color:#f92672>NOT</span> RecordVariant<span style=color:#f92672>.</span>ISRECORD <span style=color:#66d9ef>THEN</span>
|
||||
ERROR<span style=color:#f92672>(</span>NotARecordErr<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><h3 id=using-the-variant>Using the variant</h3>
|
||||
<p>The variant can be passed instead of record when calling the Page.RUN, Codeunit.RUN or Report.RUN statically:</p>
|
||||
<p>For example:</p>
|
||||
<p>Page.RUN(PageID,Variant);</p>
|
||||
<p>Codeunit.RUN(CodeunitID,Variant);</p>
|
||||
<p>Report.RUN(ReportID,Variant);</p>
|
||||
<p>These calls are identical to using an actual instance of the record, since the variant will be casted to the record automatically, with all filters, markings and values preserved.</p>
|
||||
<hr>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>Page</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span>PageID,<span style=color:#66d9ef>Variant</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>Codeunit</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span>CodeunitID,<span style=color:#66d9ef>Variant</span><span style=color:#f92672>)</span>;
|
||||
|
||||
<span style=color:#66d9ef>Report</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span>ReportID,<span style=color:#66d9ef>Variant</span><span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>These calls are identical to using an actual instance of the record, since the variant will be casted to the record automatically, with all filters, markings and values preserved.</p>
|
||||
<p>In case the variant was casted to the RecordRef (by using DataTypeManagement.GetRecordRef(RecRelatedVariant,RecordRef)), it is still possible to invoke the functions statically.</p>
|
||||
<p>The RecordRef simply needs to be casted into a variant and passed as a parameter, for example:</p>
|
||||
<p>VariantArgument := RecordRef;</p>
|
||||
<p>Page.RUN(PageID,VariantArgument);</p>
|
||||
<p>Variant can always casted back to the original record in the table specific code, exact process is described below.</p>
|
||||
<h2 id=table-specific-code>Table specific code</h2>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>VariantArgument <span style=color:#f92672>:=</span> <span style=color:#66d9ef>RecordRef</span>;
|
||||
|
||||
<span style=color:#66d9ef>Page</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span>PageID,VariantArgument<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Variant can always casted back to the original record in the table specific code, exact process is described below.</p>
|
||||
<h3 id=table-specific-code>Table specific code</h3>
|
||||
<p>To do table-specific processing, it is necessary to get the RecordRef first, since NUMBER parameter will tell us which table it is. In the table-specific code, it is possible to cast the variant back to the original record type, so data is accessible and it is possible to invoke functions.</p>
|
||||
<p>To do this, the best practice is to use the COPY function to preserve filters:</p>
|
||||
<p>SalesHeader.COPY(RecordVariant);</p>
|
||||
<p>Assigning directly such as SalesHeader := RecordVariant, is possible, however all filters will be lost.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>SalesHeader<span style=color:#f92672>.</span>COPY<span style=color:#f92672>(</span>RecordVariant<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Assigning directly such as SalesHeader := RecordVariant, is possible, however all filters will be lost.</p>
|
||||
<p>Example of table specific code:</p>
|
||||
<p>CASE RecordRef.NUMBER OF</p>
|
||||
<p>DATABASE::“Sales Header”:</p>
|
||||
<p>BEGIN</p>
|
||||
<p>SalesHeader.COPY(RecordVariant);</p>
|
||||
<p>SalesHeader.PrintDocument;</p>
|
||||
<p>END;</p>
|
||||
<p>DATABASE::“Purchase Header”:</p>
|
||||
<p>BEGIN</p>
|
||||
<p>PurchaseHeader.COPY(RecordVariant)</p>
|
||||
<p>…</p>
|
||||
<p>END;</p>
|
||||
<p>….</p>
|
||||
<p>It is a good practice to try to avoid the table specific code if possible.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>CASE</span> <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>.</span>NUMBER <span style=color:#66d9ef>OF</span>
|
||||
<span style=color:#66d9ef>DATABASE</span>::"Sales Header":
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
SalesHeader<span style=color:#f92672>.</span>COPY<span style=color:#f92672>(</span>RecordVariant<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>PrintDocument;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#66d9ef>DATABASE</span>::"Purchase Header":
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
PurchaseHeader<span style=color:#f92672>.</span>COPY<span style=color:#f92672>(</span>RecordVariant<span style=color:#f92672>)
|
||||
</span><span style=color:#f92672> ...
|
||||
</span><span style=color:#f92672> </span><span style=color:#66d9ef>END</span>;
|
||||
<span style=color:#f92672>....
|
||||
</span></code></pre></div><p>It is a good practice to try to avoid the table specific code if possible.</p>
|
||||
<p>One of the issues with table specific code is that the CASE statement can easily explode when large number of records are supported.</p>
|
||||
<p>There are two possible solutions:</p>
|
||||
<ol>
|
||||
<li>Move the calculations outside of the façade code unit and pass it in as part of the argument table.</li>
|
||||
</ol>
|
||||
<p>For example, instead of having a case like this within DocumentPrint codeunit:</p>
|
||||
<p>CASE RecordRef.NUMBER OF</p>
|
||||
<p>DATABASE::“Sales Header”:</p>
|
||||
<p>BEGIN</p>
|
||||
<p>SalesHeader.COPY(RecordVariant);</p>
|
||||
<p>CASE SalesHeader.“Document Type” OF</p>
|
||||
<p>SalesHeader.“Document Type”::Quote:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Quote”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Blanket Order”:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Blanket”);</p>
|
||||
<p>SalesHeader.“Document Type”::Order:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Order”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Return Order”:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Return”);</p>
|
||||
<p>SalesHeader.“Document Type”::Invoice:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Invoice”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Credit Memo”:</p>
|
||||
<p>ReportSelections.SETRANGE(Usage,ReportSelections.Usage::“S.Cr.Memo”);</p>
|
||||
<p>END;</p>
|
||||
<p>If the ReportSelections.Usage is simply passed into the function from outside, then the case statement is not needed at all. For example:</p>
|
||||
<p>PrintDocumentArguments.“Report Selection Usage” := SalesHeader.GetReportSelectionUsage;</p>
|
||||
<p>DocumentPrint.PrintDocument(SalesHeader,PrintDocumentArguments);</p>
|
||||
<p>Where GetReportSelection usage is coded like this:</p>
|
||||
<p>CASE SalesHeader.“Document Type” OF</p>
|
||||
<p>SalesHeader.“Document Type”::Quote:</p>
|
||||
<p>EXIT (ReportSelections.Usage::“S.Quote”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Blanket Order”:</p>
|
||||
<p>EXIT(ReportSelections.Usage::“S.Blanket”);</p>
|
||||
<p>SalesHeader.“Document Type”::Order:</p>
|
||||
<p>EXIT(ReportSelections.Usage::“S.Order”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Return Order”:</p>
|
||||
<p>EXIT(ReportSelections.Usage::“S.Return”);</p>
|
||||
<p>SalesHeader.“Document Type”::Invoice:</p>
|
||||
<p>EXIT(ReportSelections.Usage::“S.Invoice”);</p>
|
||||
<p>SalesHeader.“Document Type”::“Credit Memo”:</p>
|
||||
<p>EXIT(ReportSelections.Usage::“S.Cr.Memo”);</p>
|
||||
<p>This way the code is much more reusable and simpler to read.</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>CASE</span> <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>.</span>NUMBER <span style=color:#66d9ef>OF</span>
|
||||
<span style=color:#66d9ef>DATABASE</span>::"Sales Header":
|
||||
<span style=color:#66d9ef>BEGIN</span>
|
||||
SalesHeader<span style=color:#f92672>.</span>COPY<span style=color:#f92672>(</span>RecordVariant<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>CASE</span> SalesHeader<span style=color:#f92672>.</span>"Document Type" <span style=color:#66d9ef>OF</span>
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::Quote:
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Quote"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Blanket Order":
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Blanket"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::<span style=color:#66d9ef>Order</span>:
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Order"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Return Order":
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Return"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::Invoice:
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Invoice"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Credit Memo":
|
||||
ReportSelections<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>Usage,ReportSelections<span style=color:#f92672>.</span>Usage::"S.Cr.Memo"<span style=color:#f92672>)</span>;
|
||||
<span style=color:#66d9ef>END</span>;
|
||||
</code></pre></div><p>If the ReportSelections.Usage is simply passed into the function from outside, then the case statement is not needed at all. For example:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>PrintDocumentArguments<span style=color:#f92672>.</span>"Report Selection Usage" <span style=color:#f92672>:=</span> SalesHeader<span style=color:#f92672>.</span>GetReportSelectionUsage;
|
||||
|
||||
DocumentPrint<span style=color:#f92672>.</span>PrintDocument<span style=color:#f92672>(</span>SalesHeader,PrintDocumentArguments<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>Where GetReportSelection usage is coded like this:</p>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al><span style=color:#66d9ef>CASE</span> SalesHeader<span style=color:#f92672>.</span>"Document Type" <span style=color:#66d9ef>OF</span>
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::Quote:
|
||||
<span style=color:#66d9ef>EXIT</span> <span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Quote"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Blanket Order":
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Blanket"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::<span style=color:#66d9ef>Order</span>:
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Order"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Return Order":
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Return"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::Invoice:
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Invoice"<span style=color:#f92672>)</span>;
|
||||
SalesHeader<span style=color:#f92672>.</span>"Document Type"::"Credit Memo":
|
||||
<span style=color:#66d9ef>EXIT</span><span style=color:#f92672>(</span>ReportSelections<span style=color:#f92672>.</span>Usage::"S.Cr.Memo"<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><p>This way the code is much more reusable and simpler to read.</p>
|
||||
<ol>
|
||||
<li>Use Rules Table to replace the code with data-driven approach.</li>
|
||||
</ol>
|
||||
<p>Setup table would contain the list of the reports and their usages. Based on Table ID and usage it is possible to set filters on the setup table and run the object ID from the result.</p>
|
||||
<p>For example:</p>
|
||||
<p>ReportSelectionSetup.SETRANGE(“Table ID”, RecordRef.NUMBER);</p>
|
||||
<p>ReportSelectionSetup.SETRANGE(“Usage Type”, RecordRef.FieldValue(ArgumentTable.“Usage Type”);</p>
|
||||
<p>ReportSelectionSetup.FINDFIRST;</p>
|
||||
<p>REPORT.RUN(ReportSelectionSetup.“Report ID”,VariantRecord);</p>
|
||||
<hr>
|
||||
<h1 id=example>Example</h1>
|
||||
<div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-al data-lang=al>ReportSelectionSetup<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Table ID", <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>.</span>NUMBER<span style=color:#f92672>)</span>;
|
||||
|
||||
ReportSelectionSetup<span style=color:#f92672>.</span>SETRANGE<span style=color:#f92672>(</span>"Usage Type", <span style=color:#66d9ef>RecordRef</span><span style=color:#f92672>.</span>FieldValue<span style=color:#f92672>(</span>ArgumentTable<span style=color:#f92672>.</span>"Usage Type"<span style=color:#f92672>)</span>;
|
||||
|
||||
ReportSelectionSetup<span style=color:#f92672>.</span>FINDFIRST;
|
||||
|
||||
<span style=color:#66d9ef>REPORT</span><span style=color:#f92672>.</span>RUN<span style=color:#f92672>(</span>ReportSelectionSetup<span style=color:#f92672>.</span>"Report ID",VariantRecord<span style=color:#f92672>)</span>;
|
||||
</code></pre></div><h2 id=example>Example</h2>
|
||||
<p>The following code illustrates how the Variant Façade pattern can be used to implement the Document-Print Codeunit.</p>
|
||||
<p><a href=Picture7.png><img src=Picture7.png alt=" "></a></p>
|
||||
<p><a href=Picture8.png><img src=Picture8.png alt=" "></a></p>
|
||||
|
|
@ -397,7 +411,7 @@ ALGuidelines.Dev
|
|||
<p>Code duplication is avoided, specific code is isolated in the PrepareRecord function, there is clear extension point to add support for new records in the future. Since code is not duplicated and there is a single flow through the method, inserting hooks and events in the future will be straightforward.</p>
|
||||
<p>When adding the support for new records in most cases it is not need to change any code within the method, thus the cost of extending the usage is minimal.</p>
|
||||
<p>Note - PrepareRecord function is placed for the illustrational purposes. An improvement would be to move all of the code from the PrepareRecord function before calling the function. So for the SalesHeader and PurchaseHeaders discounts should be calculated before invoking the function. For passing of the argument it should be one of the fields in the Argument Table, thus the entire specific code would be eliminated.</p>
|
||||
<h1 id=consequences>Consequences</h1>
|
||||
<h2 id=consequences>Consequences</h2>
|
||||
<ul>
|
||||
<li>Not needed if the functionality needs to support few tables. Don’t use it as a hammer</li>
|
||||
<li>Strongly typing the records has it benefits since it is easier to find usages, errors will be visible at the compilation time.</li>
|
||||
|
|
@ -405,7 +419,7 @@ ALGuidelines.Dev
|
|||
<li>Be careful with filters and marks, if the function needs to support multiple records. Test these cases thoughtfully because with bad placement of code the filters can easily be lost.</li>
|
||||
<li>Case statements can explode if there are too many tables that require specific processing. Then it is a must to find a way to keep the number of options in the CASE statement low. The Rules Table pattern and adding specifics to the Argument Table before invoking the code could help with keep the list shorter.</li>
|
||||
</ul>
|
||||
<h1 id=nav-usages>NAV usages</h1>
|
||||
<h2 id=nav-usages>NAV usages</h2>
|
||||
<ul>
|
||||
<li>Codeunit 452 - Report Distribution Management</li>
|
||||
<li>Codeunit 700 - Page Management</li>
|
||||
|
|
@ -417,12 +431,10 @@ ALGuidelines.Dev
|
|||
<li>Codeunit 1531 - Workflow Change Rec Mgt.</li>
|
||||
<li>Codeunit 1535 - Approvals Mgmt.</li>
|
||||
</ul>
|
||||
<h1 id=related-topics>Related Topics</h1>
|
||||
<h2 id=related-topics>Related Topics</h2>
|
||||
<p>OO Facade <a href=https://en.wikipedia.org/wiki/Facade_pattern>https://en.wikipedia.org/wiki/Facade_pattern</a></p>
|
||||
<p>Argument Table pattern - <a href=/nav/w/designpatterns/245.argument-table-pattern>https://community.dynamics.com/nav/w/designpatterns/245.argument-table-pattern</a></p>
|
||||
<p>Rules Table pattern</p>
|
||||
<p>< –[if supportAnnotations]–>
|
||||
< –[endif]–></p>
|
||||
<footer class=footline>
|
||||
</footer>
|
||||
</main>
|
||||
|
|
@ -435,12 +447,12 @@ ALGuidelines.Dev
|
|||
<div style=left:-1000px;overflow:scroll;position:absolute;top:-1000px;border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px>
|
||||
<div style=border:none;box-sizing:content-box;height:200px;margin:0;padding:0;width:200px></div>
|
||||
</div>
|
||||
<script src=/js/clipboard.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644506469></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644506469></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644506469></script>
|
||||
<script src=/js/featherlight.min.js?1644506469></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644506469></script>
|
||||
<script src=/js/relearn.js?1644506469></script>
|
||||
<script src=/js/clipboard.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.min.js?1644600599></script>
|
||||
<script src=/js/perfect-scrollbar.jquery.min.js?1644600599></script>
|
||||
<script src=/js/jquery.svg.pan.zoom.js?1644600599></script>
|
||||
<script src=/js/featherlight.min.js?1644600599></script>
|
||||
<script src=/js/modernizr.custom-3.6.0.js?1644600599></script>
|
||||
<script src=/js/relearn.js?1644600599></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue