alguidelines.dev - Business Central Design Patterns – Blocked Entityhttps://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/Recent content in Blocked Entity on alguidelines.dev - Business Central Design PatternsHugo -- gohugo.ioen-usDocs: Data Driven Blocked Entityhttps://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/data-driven-blocked-entity/Mon, 01 Jan 0001 00:00:00 +0000https://alguidelines.dev/docs/navpatterns/patterns/blocked-entity/data-driven-blocked-entity/ <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">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 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 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></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">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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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></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>