This commit is contained in:
TheDoubleH 2022-02-11 17:30:04 +00:00
parent de09820554
commit e4f08bf9a7
187 changed files with 6620 additions and 6342 deletions

View file

@ -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 &ldquo;Using In-context Notifications&rdquo; 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/>&ldquo;Using In-context Notifications&rdquo;</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::&quot;Item-Check Avail.&quot;,'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>::&#34;Item-Check Avail.&#34;,<span style=color:#e6db74>&#39;ShowNotificationDetails&#39;</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>&#39;2712AD06-C48B-4C20-820E-347A60C9AD00&#39;</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::&quot;Item-Check Avail.&quot;,'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>::&#34;Item-Check Avail.&#34;,<span style=color:#e6db74>&#39;ShowNotificationDetails&#39;</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&rsquo;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&rsquo;t happen very often. The issue is that when we call <strong>SendNotification</strong>, we provide the cause object&rsquo;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>