67 lines
No EOL
15 KiB
XML
67 lines
No EOL
15 KiB
XML
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>alguidelines.dev - Business Central Design Patterns – Blocked Entity</title><link>https://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/</link><description>Recent content in Blocked Entity on alguidelines.dev - Business Central Design Patterns</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: Data Driven Blocked Entity</title><link>https://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/data-driven-blocked-entity/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/data-driven-blocked-entity/</guid><description>
|
||
<p><em>Written by Bogdan Andrei Sturzoiu, at Microsoft Development Center Copenhagen</em></p>
|
||
<h2 id="abstract">Abstract</h2>
|
||
<p>This pattern implements a generic mechanism for dynamically restricting and allowing usage of a record by the business process administrator.</p>
|
||
<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="https://alguidelines.dev/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 &ldquo;blocked&rdquo; status field on the record (either a Boolean or in the more advanced cases, an option field refining the usage).</li>
|
||
<li>Adding specific code for the record in every place where the restriction needs to be enforced.</li>
|
||
</ol>
|
||
<p>In contrast, the Data-driven Blocked Entity pattern involves adding a new record (data change) to mark the restriction, instead of adding a new field (metadata change).</p>
|
||
<h2 id="solution">Solution</h2>
|
||
<p>This pattern describes a generic mechanism of adding and lifting restrictions for any type of record.</p>
|
||
<p>The restriction mechanism has the following elements:</p>
|
||
<ol>
|
||
<li>Adding a restriction record for a specific reason (e.g. the record requires approval), which will act as a surrogate key (unique identifier) for the restricted record. This can be implemented through a workflow response, or directly, by calling the Restriction Management codeunit function.</li>
|
||
<li>Lifting the restriction when it is no longer necessary. Again, this can be done using a workflow response or directly by calling the dedicated function.</li>
|
||
<li>Consuming the restriction in the places of interest for a specific purpose. This is an application feature that requires a call to the Restriction Management codeunit to check for restrictions.</li>
|
||
</ol>
|
||
<p>Currently, the restrictions are record-based and type-less. They act as simple tokens, and they have:</p>
|
||
<ul>
|
||
<li>A reason (e.g. the record requires approval)</li>
|
||
<li>A purpose (e.g. the record cannot be posted).</li>
|
||
</ul>
|
||
<p>You must make sure to differentiate between the reason and the purpose. That is because the restriction can only be added once per record, but consumed in multiple places.</p>
|
||
<h2 id="example">Example</h2>
|
||
<p>For example, we want to restrict posting Gen. Journal Lines if a customer has not been added in Account No. field.</p>
|
||
<p>For this, the following components are needed:</p>
|
||
<ol>
|
||
<li>When a Gen. Journal Line is inserted, call RestrictRecordUsage in COD1550, either directly in the trigger or using an event subscriber.</li>
|
||
<li>When you validate a Customer No. as Account no. and Customer as Account Type, lift the restrictions by calling AllowRecordUsage in COD1550.</li>
|
||
<li>The consumption of the restriction at posting is already implemented as an event in TAB81, OnCheckGenJournalLinePostRestrictions. No further action necessary.</li>
|
||
</ol>
|
||
<h2 id="nav-usage">NAV Usage</h2>
|
||
<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 &ldquo;Add record restriction&rdquo; and &ldquo;Remove record restriction&rdquo; 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 &ldquo;Add record restriction&rdquo; workflow response:</p>
|
||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-AL" data-lang="AL"><span style="display:flex;"><span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>GETTABLE<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">Variant</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span>Workflow<span style="color:#ce5c00;font-weight:bold">.</span>GET<span style="color:#ce5c00;font-weight:bold">(</span>WorkflowStepInstance<span style="color:#ce5c00;font-weight:bold">.</span>&#34;Workflow Code&#34;<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span>RecordRestrictionMgt<span style="color:#ce5c00;font-weight:bold">.</span>RestrictRecordUsage<span style="color:#ce5c00;font-weight:bold">(</span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">RECORDID</span><span style="color:#000;font-weight:bold">,</span>STRSUBSTNO<span style="color:#ce5c00;font-weight:bold">(</span>RestrictUsageDetailsTxt<span style="color:#000;font-weight:bold">,</span>Workflow<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">Code</span><span style="color:#000;font-weight:bold">,</span>Workflow<span style="color:#ce5c00;font-weight:bold">.</span>Description<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span></code></pre></div><p>The code behind the &ldquo;Remove record restriction&rdquo; response:</p>
|
||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-AL" data-lang="AL"><span style="display:flex;"><span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>GETTABLE<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">Variant</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">CASE</span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>NUMBER<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">OF</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">DATABASE</span><span style="color:#000;font-weight:bold">::</span>&#34;Approval Entry&#34;<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">BEGIN</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecordRestrictionMgt<span style="color:#ce5c00;font-weight:bold">.</span>AllowRecordUsage<span style="color:#ce5c00;font-weight:bold">(</span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">RECORDID</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>SETTABLE<span style="color:#ce5c00;font-weight:bold">(</span>ApprovalEntry<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>GET<span style="color:#ce5c00;font-weight:bold">(</span>ApprovalEntry<span style="color:#ce5c00;font-weight:bold">.</span>&#34;Record ID to Approve&#34;<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>AllowRecordUsage<span style="color:#ce5c00;font-weight:bold">(</span>RecRef<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">END</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">DATABASE</span><span style="color:#000;font-weight:bold">::</span>&#34;Gen. Journal Batch&#34;<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">BEGIN</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span>SETTABLE<span style="color:#ce5c00;font-weight:bold">(</span>GenJournalBatch<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecordRestrictionMgt<span style="color:#ce5c00;font-weight:bold">.</span>AllowGenJournalBatchUsage<span style="color:#ce5c00;font-weight:bold">(</span>GenJournalBatch<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">END</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">ELSE</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span>RecordRestrictionMgt<span style="color:#ce5c00;font-weight:bold">.</span>AllowRecordUsage<span style="color:#ce5c00;font-weight:bold">(</span>RecRef<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">RECORDID</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">END</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||
</span></span></span></code></pre></div><p>Notice how lifting a restriction for a Gen. Journal Batch involves lifting all the restrictions for the individual journal lines in the batch (hence the special branching of the code).</p>
|
||
<h2 id="consequences">Consequences</h2>
|
||
<p>Currently, there can only be one restriction per record. There are no restriction types.</p>
|
||
<p>In the future, a type field should be added to the restriction table, to allow adding restrictions for different purposes, and to refine their consumption. For example, a posting restriction might only be enforced for restrictions originating from approvals.</p>
|
||
<h2 id="nav-versions">NAV Versions</h2>
|
||
<p>This pattern has been introduced in Dynamics NAV 2016.</p></description></item></channel></rss> |