{"id":697,"date":"2022-05-07T19:35:57","date_gmt":"2022-05-07T17:35:57","guid":{"rendered":"https:\/\/jonathanpapa.com\/blog\/?p=697"},"modified":"2023-04-11T18:47:10","modified_gmt":"2023-04-11T16:47:10","slug":"di-transactions-deeper-look","status":"publish","type":"post","link":"https:\/\/jonathanpapa.com\/blog\/2022\/05\/07\/di-transactions-deeper-look\/","title":{"rendered":"SAP B1 &#8211; DI Transactions, a deeper look."},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"697\" class=\"elementor elementor-697\">\n\t\t\t\t\t\t<div class=\"elementor-inner\">\n\t\t\t\t<div class=\"elementor-section-wrap\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-87d8636 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"87d8636\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d38d240\" data-id=\"d38d240\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-920cd98 elementor-widget elementor-widget-heading\" data-id=\"920cd98\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Introduction<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-18833d1 elementor-widget elementor-widget-text-editor\" data-id=\"18833d1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>In this tutorial, we will discuss the different approaches to use when packing multiple business operations together in <strong>SAP Business One\u00a0<\/strong>and how we can avoid common mistakes that lead to incomplete processes.<\/p>\n<p>This article can be useful if:<\/p>\n<ol>\n<li>You&rsquo;re planning on building an interface for SAP B1 and want to know your options.<\/li>\n<li>You want to optimize an existing process for one of your customer where multiple business objects are being added and\/or updated.<\/li>\n<li>You wish to learn more about how transactions work in SAP B1.<\/li>\n<\/ol>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ca18ac4 elementor-widget elementor-widget-table-of-contents\" data-id=\"ca18ac4\" data-element_type=\"widget\" data-settings=\"{&quot;exclude_headings_by_selector&quot;:[],&quot;headings_by_tags&quot;:[&quot;h2&quot;,&quot;h3&quot;,&quot;h4&quot;,&quot;h5&quot;,&quot;h6&quot;],&quot;marker_view&quot;:&quot;numbers&quot;,&quot;hierarchical_view&quot;:&quot;yes&quot;,&quot;min_height&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;min_height_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;min_height_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}\" data-widget_type=\"table-of-contents.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-toc__header\">\n\t\t\t<h4 class=\"elementor-toc__header-title\">\n\t\t\t\tTable of Contents\t\t\t<\/h4>\n\t\t\t\t\t<\/div>\n\t\t<div class=\"elementor-toc__body\">\n\t\t\t<div class=\"elementor-toc__spinner-container\">\n\t\t\t\t<i class=\"elementor-toc__spinner eicon-animation-spin eicon-loading\" aria-hidden=\"true\"><\/i>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-8befbb0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8befbb0\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0a73f0d\" data-id=\"0a73f0d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4465c98 elementor-widget elementor-widget-heading\" data-id=\"4465c98\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Context<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-56f0318 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"56f0318\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6aa16fb\" data-id=\"6aa16fb\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-60bca0b elementor-widget elementor-widget-text-editor\" data-id=\"60bca0b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You customer wants you to develop an interface where both an order and its invoice are being added to the system <span style=\"text-decoration: underline;\"><strong>together<\/strong><\/span>.<\/p><p>Let us take as an example an order with two lines and its corresponding invoice.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-542600e elementor-widget elementor-widget-image\" data-id=\"542600e\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img width=\"812\" height=\"117\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-1024x148.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-1024x148.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-300x43.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-768x111.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-1536x221.png 1536w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ordertoinv-2048x295.png 2048w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-dffa2ab elementor-widget elementor-widget-text-editor\" data-id=\"dffa2ab\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>In SAP B1, a document flow is maintained at line level. In this case:<\/p><ul><li>The first line of the invoice is linked to the first line of the order.<\/li><li>The second line of the invoice is linked to the first line of the order.<\/li><\/ul><p>Since the invoice is created <strong>after<\/strong> the order; for this relation to work, you need to know in advance the unique identifier of the order. Otherwise, you cannot bind these four lines together.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6602f01 elementor-widget elementor-widget-heading\" data-id=\"6602f01\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">What not do do \u274c<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-082755a elementor-widget elementor-widget-text-editor\" data-id=\"082755a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>If we break this down, the natural way of handling it would be:<\/p><ol><li>First, add the sales order<\/li><li>Retrieve the unique identifier assigned by the system (which is called the <em><strong>DocEntry<\/strong><\/em>)<\/li><li>Create the invoice based on the order&rsquo;s <em><strong>DocEntry\u00a0<\/strong><\/em>and add it.<\/li><\/ol>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cb1e839 elementor-widget elementor-widget-image\" data-id=\"cb1e839\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"addDocTwoPassGeneric\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODU0LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL2FkZERvY1R3b1Bhc3NHZW5lcmljLnBuZyJ9\">\n\t\t\t\t\t\t\t<img width=\"768\" height=\"667\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric-768x667.png\" class=\"attachment-medium_large size-medium_large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric-768x667.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric-300x261.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric-1024x890.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocTwoPassGeneric.png 1428w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Add an order and an invoice with two separate calls (happy scenario).<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-50919da elementor-widget elementor-widget-text-editor\" data-id=\"50919da\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>This is working well&#8230; Unless the addition of the A\/R Invoice fails. This would result in an orphaned order and you would need to handle this situation by either:<\/p><ul><li>Cancelling the order in the B1 client, then retrying the scenario. But then you&rsquo;d need to manage the fact that the order was already created.<br \/>Or<\/li><li>Creating the invoice in the B1 client (via the <em><strong>Copy To<\/strong><\/em> button) without retrying the scenario.<\/li><\/ul><p>In other words, you&rsquo;d need a manual operation to fix it, and we don&rsquo;t want that. Instead, we want to perform those two operations in one pass and rollback if either one of them fails.<\/p><p>This particular point is often referred as <em><strong>Atomicity<\/strong> <\/em>in the <em><strong>ACID<\/strong> <\/em>principles. Quoting Wikipedia:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f83e776 elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"f83e776\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\tAtomicity\n\nTransactions are often composed of multiple statements. Atomicity guarantees that each transaction is treated as a single \"unit\", which either succeeds completely or fails completely: if any of the statements constituting a transaction fails to complete, the entire transaction fails and the database is left unchanged.\t\t\t<\/p>\n\t\t\t\t\t\t\t<footer>\n\t\t\t\t\t\t\t\t\t\t\t<cite class=\"elementor-blockquote__author\">Wikipedia<\/cite>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/footer>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-29fc291 elementor-widget elementor-widget-text-editor\" data-id=\"29fc291\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>In this example, this could be a DI error at invoice creation:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c4332a5 elementor-widget elementor-widget-code-highlight\" data-id=\"c4332a5\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-json line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-json\">\n\t\t\t\t\t<xmp>{\r\n   \"error\" : {\r\n      \"code\" : \"-10\",\r\n      \"message\" : \"Quantity falls into negative inventory  [DocumentLines.ItemCode][line: 1]\"\r\n   }\r\n}<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-450fc70 elementor-widget elementor-widget-text-editor\" data-id=\"450fc70\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>&#8230; as you can still add the order even if you don&rsquo;t have enough quantity in stock but not the invoice.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-605cd7a elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"605cd7a\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1fa9377\" data-id=\"1fa9377\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d9a2cf4 elementor-widget elementor-widget-heading\" data-id=\"d9a2cf4\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Transactions to the rescue!<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-759d1dc elementor-widget elementor-widget-text-editor\" data-id=\"759d1dc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>We can address this problem with the use of transactions, simply said:<\/p><ol><li>Open a transaction<\/li><li>Add order<\/li><li>Add invoice<\/li><li>Close transaction<\/li><\/ol><p>Luckily for us, SAP addresses this issue by providing solutions to handle transactions:<\/p><ol><li>With the D<strong>I-API<\/strong><\/li><li>With the <strong>Service Layer \/$batch<\/strong> endpoint<\/li><li>With a <strong>script extension<\/strong> (user-made JS script installed on top of the service layer).<\/li><\/ol><p>In this article, we will see the differences between these three methods. Which one you&rsquo;ll use depends on the type of project you&rsquo;re building (API\/stand-alone executable program) and the amount of flexibility you need inside of your transactions.\u00a0<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0678edd elementor-widget elementor-widget-heading\" data-id=\"0678edd\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Transactions' pitfalls<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-128ab48 elementor-widget elementor-widget-text-editor\" data-id=\"128ab48\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You may wonder what&rsquo;s really going on when you&rsquo;re using transactions. An easy way to track it down for MSSQL versions of SAP is to open the SQL Server Profiler and invoke the <strong>StartTransaction()<\/strong> and <strong>EndTransaction()<\/strong> methods of the <strong>DI-API<\/strong>.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fce03b1 elementor-widget elementor-widget-image\" data-id=\"fce03b1\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"Starting and ending a transaction\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6OTcwLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL3VuZGVydGhlaG9vZC5wbmcifQ%3D%3D\">\n\t\t\t\t\t\t\t<img width=\"812\" height=\"186\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood-1024x235.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood-1024x235.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood-300x69.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood-768x177.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/underthehood.png 1144w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">What happens in the database when we start and end a B1 DI transaction.<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ba5dac1 elementor-widget elementor-widget-text-editor\" data-id=\"ba5dac1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>We can see on the screenshot that the isolation level is set to <strong>SERIALIZABLE<\/strong> when starting a transaction. Taking a look at microsoft documentation:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-da2e2ca elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"da2e2ca\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\t<b>SERIALIZABLE<\/b>\n\n<ol>\n<ul>Statements cannot read data that has been modified but not yet committed by other transactions.<\/ul>\n<ul>No other transactions can modify data that has been read by the current transaction until the current transaction completes.<\/ul>\n<ul>Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.<\/ul>\n<\/ol>\t\t\t<\/p>\n\t\t\t\t\t\t\t<footer>\n\t\t\t\t\t\t\t\t\t\t\t<cite class=\"elementor-blockquote__author\"><a target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/t-sql\/statements\/set-transaction-isolation-level-transact-sql?redirectedfrom=MSDN&view=sql-server-ver16\">Microsoft Documentation (click to open in new tab).<\/a><\/cite>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/footer>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-046f5f0 elementor-widget elementor-widget-text-editor\" data-id=\"046f5f0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Just trying to draw your attention on the fact that transactions do come with a cost and can even freeze the B1 client for users that are tyring to access modified data in your transaction.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-38343fc elementor-widget elementor-widget-text-editor\" data-id=\"38343fc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>It&rsquo;s up to you to judge whether the use of transactions are really needed, especially if you&rsquo;re running such a process during business hours. I would simply advise to:<\/p><ol><li>Do as many things as you can prior to starting your transaction and only start it when you&rsquo;re ready to send the data to the ERP.<\/li><li>Avoid time-consuming operations within a transaction.<\/li><li>Avoid packing too many business operations within a single transaction.<\/li><\/ol><p><span class=\"highlightBold\">The next sections will all deal with transactions, so keep that in mind that the warning above applies for all of them.<\/span><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3966a03 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3966a03\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7ccc73c\" data-id=\"7ccc73c\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6bb8e45 elementor-widget elementor-widget-heading\" data-id=\"6bb8e45\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">DI-API - With transactions<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-742ebcb elementor-widget elementor-widget-text-editor\" data-id=\"742ebcb\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>DI-API handles transactions. Let us take the same example : adding an order and an invoice in a single transaction (<strong>see highlighted lines #17 and #47<\/strong>):<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2302d69 elementor-widget elementor-widget-code-highlight\" data-id=\"2302d69\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"17,47\" class=\"highlight-height language-csharp line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-csharp\">\n\t\t\t\t\t<xmp>            SAPbobsCOM.IDocuments\r\n                oOrder = oCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oOrders) as SAPbobsCOM.IDocuments,\r\n                oInvoice = oCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oInvoices) as SAPbobsCOM.IDocuments;\r\n\r\n            \/\/ Preparing the order payload\r\n            oOrder.CardCode = \"C001\";\r\n            oOrder.DocDate = DateTime.Today;\r\n            oOrder.DocDueDate = DateTime.Today.AddDays(30);\r\n            oOrder.Lines.SetCurrentLine(0); \/\/ Not needed, for the sake of clarity\r\n            oOrder.Lines.ItemCode = \"A0001\";\r\n            oOrder.Lines.Quantity = 1;\r\n            oOrder.Lines.Price = 50;\r\n\r\n            try\r\n            {\r\n                \/\/  ***************** BEGIN TRANSACTION *****************\r\n                oCompany.StartTransaction();\r\n\r\n                if (oOrder.Add() != 0)\r\n                {\r\n                    throw new Exception(oCompany.GetLastErrorDescription());\r\n                }\r\n\r\n                \/\/ Since we are in a transaction, we cannot get the DocEntry out of the order object\r\n                \/\/ Else, we will use a small trick\r\n                int orderDocEntry = Int32.Parse(oCompany.GetNewObjectKey(), CultureInfo.InvariantCulture);\r\n\r\n                \/\/ The order was successfully added!\r\n                \/\/ Preparing the invoice payload\r\n                oInvoice.CardCode = oOrder.CardCode;\r\n                oInvoice.DocDate = oOrder.DocDate;\r\n                oInvoice.DocDueDate = oOrder.DocDueDate;\r\n                oInvoice.Lines.ItemCode = oOrder.Lines.ItemCode;\r\n                oInvoice.Lines.Quantity = oOrder.Lines.Quantity;\r\n                oInvoice.Lines.Price = oOrder.Lines.Price;\r\n                oInvoice.Lines.SetCurrentLine(0); \/\/ Not needed, for the sake of clarity\r\n                oInvoice.Lines.BaseEntry = orderDocEntry;\r\n                oInvoice.Lines.BaseLine = 0;\r\n                oInvoice.Lines.BaseType = (int)SAPbobsCOM.BoObjectTypes.oOrders;\r\n\r\n                if (oInvoice.Add() != 0)\r\n                {\r\n                    throw new Exception(oCompany.GetLastErrorDescription());\r\n                }\r\n\r\n                \/\/ Both order and invoices were successfully added, commit transaction!\r\n                oCompany.EndTransaction(SAPbobsCOM.BoWfTransOpt.wf_Commit);\r\n                \/\/  ***************** END TRANSACTION *****************\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                \/\/ Should any DI operation fails, the transaction is automatically rollback\r\n                \/\/ We don't need to call EndTransaction here\r\n\r\n                \/\/ However, we can display the error message :)\r\n                Console.WriteLine(ex.Message);\r\n            }<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-a532055 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a532055\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-0367e9c\" data-id=\"0367e9c\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3624492 elementor-widget elementor-widget-heading\" data-id=\"3624492\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Advantages<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-37494f4 elementor-widget elementor-widget-text-editor\" data-id=\"37494f4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You can&rsquo;t beat the DI-API flexibility. After opening the transaction with the use of oCompany.StartTransaction(), you can pretty much do whatever you want. This is both useful and dangerous.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-17fb516\" data-id=\"17fb516\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3ab5d09 elementor-widget elementor-widget-heading\" data-id=\"3ab5d09\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Drawbacks<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2abd6dd elementor-widget elementor-widget-text-editor\" data-id=\"2abd6dd\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>The DI-API is not meant to be used for a Web API project where lots of concurrent requests can be received and treated. However, you can perfectly use this in either a stand-alone program or an add-on.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-0bae11e elementor-widget elementor-widget-text-editor\" data-id=\"0bae11e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Don&rsquo;t forget:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c130bbf elementor-widget elementor-widget-testimonial\" data-id=\"c130bbf\" data-element_type=\"widget\" data-widget_type=\"testimonial.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-testimonial-wrapper\">\n\t\t\t\t\t\t\t<div class=\"elementor-testimonial-content\">With great power comes great responsibility.<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-testimonial-meta elementor-has-image elementor-testimonial-image-position-aside\">\n\t\t\t\t<div class=\"elementor-testimonial-meta-inner\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-testimonial-image\">\n\t\t\t\t\t\t\t<img width=\"300\" height=\"169\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/mqdefault-300x169.jpg\" class=\"attachment-medium size-medium\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-testimonial-details\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-testimonial-name\">Uncle Ben<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-testimonial-job\">After finding out he froze all B1 clients of his customer.<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b82a787 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b82a787\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-84f8c30\" data-id=\"84f8c30\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-da3791c elementor-widget elementor-widget-heading\" data-id=\"da3791c\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Service Layer - Batch without references<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e0d0ba5 elementor-widget elementor-widget-text-editor\" data-id=\"e0d0ba5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>If you&rsquo;ve worked with the service layer before, you may have noticed that it does support batch operations. What does that mean? Taken from the documentation:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-502255c elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"502255c\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\tService Layer supports executing multiple operations sent in a single HTTP request through the use of batching. A\nbatch request must be represented as a Multipart MIME (Multipurpose Internet Mail Extensions) v1.0 message.\t\t\t<\/p>\n\t\t\t\t\t\t\t<footer>\n\t\t\t\t\t\t\t\t\t\t\t<cite class=\"elementor-blockquote__author\">SAP Document - Working with SAP Business One Service Layer<\/cite>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/footer>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-01c0b20 elementor-widget elementor-widget-text-editor\" data-id=\"01c0b20\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Let&rsquo;s start with a very simple case where we&rsquo;ll add<strong> two new items<\/strong> (OITM records) in the system with a single API call:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8e67d55 elementor-widget-divider--view-line_text elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"8e67d55\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tService layer request (Begin)\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6b975b5 elementor-widget elementor-widget-text-editor\" data-id=\"6b975b5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p><strong>POST<\/strong>\u00a0 \u00a0 \u00a0https:\/\/:50000\/b1s\/v1\/$batch<br \/>Content-Type: multipart\/mixed;boundary=ad20e139-15ad-448b-9fe6-9af9d32c6ceb<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e28c7fa elementor-widget elementor-widget-code-highlight\" data-id=\"e28c7fa\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"7,18\" class=\"highlight-height language-html line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-html\">\n\t\t\t\t\t<xmp>--ad20e139-15ad-448b-9fe6-9af9d32c6ceb\r\nContent-Type: multipart\/mixed; boundary=changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\n\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\nContent-Type: application\/http; msgtype=request\r\ncontent-transfer-encoding: binary\r\nContent-ID:1\r\n\r\nPOST \/b1s\/v1\/Items\r\n\r\n{\r\n    \"ItemCode\":\"A0001\",\r\n    \"ItemName\": \"A first item\"\r\n}\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\nContent-Type: application\/http; msgtype=request\r\ncontent-transfer-encoding: binary\r\nContent-ID:2\r\n\r\nPOST \/b1s\/v1\/Items\r\n\r\n{\r\n    \"ItemCode\":\"A0002\",\r\n    \"ItemName\": \"A second item\"\r\n}\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c--\r\n\r\n--ad20e139-15ad-448b-9fe6-9af9d32c6ceb--\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-34822d8 elementor-widget-divider--view-line_text elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"34822d8\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tService layer request (End)\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ded5461 elementor-widget elementor-widget-text-editor\" data-id=\"ded5461\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>I have highlighted lines 7 and 18 because they identify both requests with a unique id (with the use of the <em><strong>Content-ID<\/strong> <\/em>header), this will be important for the next part.<\/p><p>This all works pretty well! We&rsquo;ve created our two items, but they do not share any common property. And we don&rsquo;t need any information from Item #1 in order to create Item #2.<\/p><p>This is slightly different from what we&rsquo;ve seen above where we needed the information of the order in order to create the invoice.<\/p><p><em><strong>So how can we achieve the same thing in such case?<\/strong><\/em><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-48b495f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"48b495f\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-e5bf729\" data-id=\"e5bf729\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-716d898 elementor-widget elementor-widget-heading\" data-id=\"716d898\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Advantages<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1ce1ed5 elementor-widget elementor-widget-text-editor\" data-id=\"1ce1ed5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li>Easy to manage, you only need to understand how to forge multipart requests.<\/li><li>A single HTTP call to perform all of your operations.<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-d47d76f\" data-id=\"d47d76f\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a912708 elementor-widget elementor-widget-heading\" data-id=\"a912708\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Drawbacks<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3a1001e elementor-widget elementor-widget-text-editor\" data-id=\"3a1001e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li>You have less flexibility than DI-API as you can only send basic CRUD operations packed together.<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-8d45c5c elementor-widget elementor-widget-shortcode\" data-id=\"8d45c5c\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-shortcode\"><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b83378f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b83378f\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-97fcbdc\" data-id=\"97fcbdc\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-dcb6d1e elementor-widget elementor-widget-heading\" data-id=\"dcb6d1e\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Service Layer - Batch with references<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1b5f635 elementor-widget elementor-widget-text-editor\" data-id=\"1b5f635\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>For that purpose, the OData protocol introduced a keyword to reference an object within the same batch payload. Taken from the documentation:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-08c33fe elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"08c33fe\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\tReferencing Content ID: New entities created by a POST request within a change set can be referenced by\nsubsequent requests within the same change set by referring to the value of the Content-ID header prefixed\nwith a $ character. When used in this way, $<Content-ID> acts as an alias for the URI that identifies the new\nentity.\n\t\t\t<\/p>\n\t\t\t\t\t\t\t<footer>\n\t\t\t\t\t\t\t\t\t\t\t<cite class=\"elementor-blockquote__author\">SAP Document - Working with SAP Business One Service Layer<\/cite>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/footer>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-95c2c6e elementor-widget elementor-widget-text-editor\" data-id=\"95c2c6e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\tLet&rsquo;s now try to reproduce our scenario where we want to add an order <strong>and<\/strong> its linked invoice in a <span style=\"text-decoration: underline;\"><strong>single<\/strong> <\/span>API call.\n<br\/>\nIn the payload below, the <em><span class=\"consolas\">DocEntry<\/span><\/em> of the order is then used in the invoice payload as <span class=\"consolas\">$1<\/span> to fill in the <span class=\"consolas\">BaseEntry<\/span> of the invoice line.\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b460818 elementor-widget-divider--view-line_text elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"b460818\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tService layer request (Begin)\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-59f6a66 elementor-widget elementor-widget-text-editor\" data-id=\"59f6a66\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p><strong>POST<\/strong>\u00a0 \u00a0 \u00a0https:\/\/:50000\/b1s\/v1\/$batch<br \/>Content-Type: multipart\/mixed;boundary=ad20e139-15ad-448b-9fe6-9af9d32c6ceb<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-47e451b elementor-widget elementor-widget-code-highlight\" data-id=\"47e451b\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"7,41\" class=\"highlight-height language-html line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-html\">\n\t\t\t\t\t<xmp>--ad20e139-15ad-448b-9fe6-9af9d32c6ceb\r\nContent-Type: multipart\/mixed; boundary=changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\n\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\nContent-Type: application\/http; msgtype=request\r\ncontent-transfer-encoding: binary\r\nContent-ID:1\r\n\r\nPOST \/b1s\/v1\/Orders\r\n\r\n{\r\n    \"CardCode\":\"C001\",\r\n    \"DocDate\":\"2022-05-07\",\r\n    \"DocDueDate\":\"2022-05-30\",\r\n    \"DocumentLines\":[\r\n        {\r\n            \"LineNum\":0,\r\n            \"ItemCode\": \"A0001\",\r\n            \"Quantity\":1,\r\n            \"Price\": 50\r\n        }\r\n    ]\r\n}\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c\r\nContent-Type: application\/http; msgtype=request\r\ncontent-transfer-encoding: binary\r\nContent-ID:2\r\n\r\nPOST \/b1s\/v1\/Invoices\r\n\r\n{\r\n    \"CardCode\":\"C001\",\r\n    \"DocDate\":\"2022-05-07\",\r\n    \"DocumentLines\":[\r\n        {\r\n            \"LineNum\":0,\r\n            \"ItemCode\": \"A0001\",\r\n            \"Quantity\":1,\r\n            \"Price\": 50,\r\n            \"BaseType\" : 17,\r\n            \"BaseEntry\" : $1,\r\n            \"BaseLine\" : 0\r\n        }\r\n    ]\r\n}\r\n--changeset_2c0c74e9-52df-4816-992e-beed5a3a1b0c--\r\n\r\n--ad20e139-15ad-448b-9fe6-9af9d32c6ceb--\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2471bdd elementor-widget-divider--view-line_text elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"2471bdd\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tService layer request (End)\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c63a606 elementor-widget elementor-widget-text-editor\" data-id=\"c63a606\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>This single API call contains:<\/p><ol><li>The creation of the <i>Sales Order<\/i> (<em><strong>Content-ID<\/strong><\/em> 1)<\/li><li>The creation of the <i>A\/R Invoice<\/i> (<em><strong>Content-ID<\/strong><\/em> 2)<\/li><\/ol><p>I have highlighted lines 7 and 41 because this is where the magic happens:<\/p><ul><li>The <i>Sales Order<\/i> payload is identified with Content-ID 1.<\/li><li>In the <em>A\/R Invoice<\/em> line #0, we reference the order&rsquo;s\u00a0<span class=\"consolas\">DocEntry<\/span>\u00a0(that it not known at this point)\u00a0by providing the <span class=\"consolas\">Content-ID<\/span> number prefixed with a dollar sign <span class=\"consolas\">$<\/span>.<\/li><\/ul><p>Should either one of these two requests fails, both documents won&rsquo;t be added to the system!<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-02bb890 elementor-widget elementor-widget-text-editor\" data-id=\"02bb890\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Graphically:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c7cd0a8 elementor-widget elementor-widget-image\" data-id=\"c7cd0a8\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"addDocOnePassv3\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODQ0LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL2FkZERvY09uZVBhc3N2My5wbmcifQ%3D%3D\">\n\t\t\t\t\t\t\t<img width=\"768\" height=\"566\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3-768x566.png\" class=\"attachment-medium_large size-medium_large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3-768x566.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3-300x221.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3-1024x755.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3-1536x1133.png 1536w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/addDocOnePassv3.png 1714w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Add two documents in a single Service Layer call<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-22591be elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"22591be\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\tYou could also use the <b>b1s\/v1\/$batch<\/b> endpoint to send two independent requests by specifying multiple changesets. In this case, all requests inside the payload will be treated without consequences on the rest. Meaning that you can have one failed requests amongst the payload.\t\t\t<\/p>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7984ca0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7984ca0\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3349469\" data-id=\"3349469\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5bb9a24 elementor-widget elementor-widget-heading\" data-id=\"5bb9a24\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Service Layer - With user-transactions<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-701c38a elementor-widget elementor-widget-text-editor\" data-id=\"701c38a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Here is the interesting part, how can we get :<\/p><ul><li>A tool that is adapted for web architectures<\/li><li>With the same flexibility as the DI-API (C#)<\/li><\/ul><p>The answer lies in service layer script extensions, relying on the <em><strong>B1 Javascript SDK<\/strong><\/em>.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fb6f9b1 elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"fb6f9b1\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\t\u26a0\ufe0f<span style=\"margin-left:5px;\"\/> SAP limits the number of operations to 10 within a same javascript-extension transaction.\t\t\t<\/p>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8955c39 elementor-widget elementor-widget-text-editor\" data-id=\"8955c39\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Since I got a MSSQL B1 test environement, I can find the B1 JS SDK in:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8b07be9 elementor-widget elementor-widget-code-highlight\" data-id=\"8b07be9\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default  \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript \">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>C:\\Program Files\\SAP\\SAP Business One ServerTools\\ServiceLayer\\scripts\\b1s_sdk<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b42b835 elementor-widget elementor-widget-text-editor\" data-id=\"b42b835\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>The SDK is also available for Service Layer version for SAP HANA.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-938febd elementor-widget elementor-widget-heading\" data-id=\"938febd\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Coding the script<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-94df563 elementor-widget elementor-widget-text-editor\" data-id=\"94df563\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Let&rsquo;s see how that works for us by creating a small sample and using the B1 Javascript SDK. For that, we will create a directory and open it with VSCode.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c1678d1 elementor-widget elementor-widget-code-highlight\" data-id=\"c1678d1\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default  \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript \">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>mkdir b1sl-jssdk-sample\ncd b1sl-jssdk-sample\ncode .<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-485681c elementor-widget elementor-widget-text-editor\" data-id=\"485681c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Then, we will create a new file called <em><strong>main.js<\/strong><\/em> (the name is not important) and create an entry function for each of the HTTP Verbs : <strong><em>GET<\/em><\/strong>, <em><strong>POST<\/strong><\/em>, <em><strong>PATCH<\/strong> <\/em>and <em><strong>DELETE<\/strong><\/em>:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4b6624b elementor-widget elementor-widget-code-highlight\" data-id=\"4b6624b\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>\/\/The entry function for http request with the GET method\r\nfunction GET() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction POST() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction PATCH() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction DELETE() {}<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3e02709 elementor-widget elementor-widget-text-editor\" data-id=\"3e02709\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>In order to use the SDK, we will copy\/paste the whole content of the <em><strong>b1s_sdk<\/strong><\/em> folder in it. Both <em><strong>main.js<\/strong><\/em> and SDK files need to be in the same directory.<\/p><p>If, like me, you&rsquo;re using VSCode, this is how it should look like at this point:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-808ed12 elementor-widget__width-inherit elementor-widget elementor-widget-image\" data-id=\"808ed12\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"vscode-1b\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6NzgxLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL3ZzY29kZS0xYi5wbmcifQ%3D%3D\">\n\t\t\t\t\t\t\t<img width=\"1182\" height=\"477\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b.png\" class=\"attachment-full size-full\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b.png 1182w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b-300x121.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b-1024x413.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/vscode-1b-768x310.png 768w\" sizes=\"(max-width: 1182px) 100vw, 1182px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6fffb1e elementor-widget elementor-widget-text-editor\" data-id=\"6fffb1e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>We will now load all relevant files we&rsquo;d need for our scenario by adding these 5 lines of code at the beginning of our file:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fc87a48 elementor-widget elementor-widget-code-highlight\" data-id=\"fc87a48\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"1-4\" class=\"highlight-height language-javascript line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>var HttpModule = require(\".\/HttpModule\");\r\nvar ServiceLayerContext = require(\".\/ServiceLayerContext\");\r\nvar Document = require(\".\/EntityType\/Document\");\r\nvar DocumentLine = require(\".\/ComplexType\/DocumentLine\");\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction GET() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction POST() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction PATCH() {}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction DELETE() {}\r\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-59214b7 elementor-widget elementor-widget-text-editor\" data-id=\"59214b7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Let&rsquo;s now try and reproduce our DI-API scenario with the javascript SDK. There are some slight differences but you should understand pretty well what&rsquo;s going on.<\/p><p>The code below is a rough translation of the C# code:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-199bbc9 elementor-widget elementor-widget-code-highlight\" data-id=\"199bbc9\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>\/\/The entry function for http request with the GET method\r\nfunction POST() {\r\n  console.log(\"POST Method was called.\");\r\n\r\n  let oServiceLayerContext = new ServiceLayerContext();\r\n\r\n  \/\/ Preparing the order payload\r\n  \/\/ We will prepare as many things as possible before starting the transaction\r\n  let oOrder = new Document();\r\n  oOrder.CardCode = \"C001\";\r\n  oOrder.DocDate = \"2022-01-01\";\r\n  oOrder.DocDueDate = \"2022-01-31\";\r\n\r\n  let oOrderLine = new DocumentLine();\r\n  oOrderLine.ItemCode = \"A0001\";\r\n  oOrderLine.Quantity = 1;\r\n  oOrderLine.Price = 50;\r\n\r\n  oOrder.DocumentLines = [oOrderLine];\r\n\r\n  console.log(JSON.stringify(oOrder));\r\n\r\n  try {\r\n    \/\/ Starting our transaction\r\n    oServiceLayerContext.startTransaction();\r\n\r\n    \/** @type {SAPB1.DataServiceResponse} *\/\r\n    let oAddResult = oServiceLayerContext.Orders.add(oOrder);\r\n\r\n    console.log(\"*** Order add result ***\");\r\n    console.log(JSON.stringify(oAddResult, null, 4));\r\n\r\n    if (!oAddResult.isOK()) {\r\n      throw HttpModule.ScriptException(\r\n        HttpModule.HttpStatus.HTTP_BAD_REQUEST,\r\n        oAddResult.getErrMsg()\r\n      );\r\n    }\r\n\r\n    \/\/ The order was successfully added!\r\n    \/\/ Preparing the invoice payload\r\n    let oInvoice = new Document();\r\n    oInvoice.CardCode = oOrder.CardCode;\r\n    oInvoice.DocDate = oOrder.DocDate;\r\n    oInvoice.DocDueDate = oOrder.DocDueDate;\r\n\r\n    let oInvoiceLine = new DocumentLine();\r\n    oInvoiceLine.ItemCode = oOrderLine.ItemCode;\r\n    oInvoiceLine.Quantity = oOrderLine.Quantity;\r\n    oInvoiceLine.Price = oOrderLine.Price;\r\n\r\n    \/\/ Unlike the DI-API, we can directly get the DocEntry of the newly-created invoice out of the SL response\r\n    oInvoiceLine.BaseEntry = oAddResult.body.DocEntry;\r\n    oInvoiceLine.BaseLine = 0;\r\n    oInvoiceLine.BaseType = 17; \/\/ Object type of Sales Order is 17\r\n\r\n    oInvoice.DocumentLines = [oInvoiceLine];\r\n\r\n    \/\/ Log invoice content\r\n    console.log(JSON.stringify(oInvoice));\r\n\r\n    \/\/ Finally, add the invoice\r\n    oAddResult = oServiceLayerContext.Invoices.add(oInvoice);\r\n\r\n    console.log(\"*** Invoice add result ***\");\r\n    console.log(JSON.stringify(oAddResult, null, 4));\r\n\r\n    if (!oAddResult.isOK()) {\r\n      throw HttpModule.ScriptException(\r\n        HttpModule.HttpStatus.HTTP_BAD_REQUEST,\r\n        oAddResult.getErrMsg()\r\n      );\r\n    }\r\n\r\n    \/\/ If both order and invoice were added, commit transaction\r\n    oServiceLayerContext.commitTransaction();\r\n\r\n    console.log(\"POST Method ended.\");\r\n\r\n    \/\/ We will return an HTTP Status Code 201 (Created) + the information of both order and invoice\r\n    HttpModule.response.send(HttpModule.HttpStatus.HTTP_CREATED, {\r\n      Order: oOrder,\r\n      Invoice: oInvoice,\r\n    });\r\n  } catch (oError) {\r\n    \/\/ Unlike the DI-API, we need to manually rollback the transaction\r\n    oServiceLayerContext.rollbackTransaction();\r\n\r\n    \/\/ Return an HTTP error response\r\n    HttpModule.response.send(HttpModule.HttpStatus.HTTP_BAD_REQUEST, oError);\r\n  }\r\n}<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3d56972 elementor-widget elementor-widget-text-editor\" data-id=\"3d56972\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Side note: I am calling the console.log method that will ultimately logs information in the Service Layer installation folder.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1a47cd5 elementor-widget elementor-widget-code-highlight\" data-id=\"1a47cd5\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript \">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>C:\\Program Files\\SAP\\SAP Business One ServerTools\\ServiceLayer\\logs\\script<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f8a1488 elementor-widget elementor-widget-text-editor\" data-id=\"f8a1488\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>We will prevent the user from calling the other three methods by simply providing an HTTP response code<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-eebf736 elementor-widget elementor-widget-code-highlight\" data-id=\"eebf736\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-tomorrow copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-javascript line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-javascript\">\n\t\t\t\t\t<xmp>\/\/The entry function for http request with the GET method\r\nfunction GET() {\r\n  HttpModule.response.send(HttpModule.HttpStatus.HTTP_METHOD_NOT_ALLOWED, null);\r\n}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction PATCH() {\r\n  HttpModule.response.send(HttpModule.HttpStatus.HTTP_METHOD_NOT_ALLOWED, null);\r\n}\r\n\r\n\/\/The entry function for http request with the GET method\r\nfunction DELETE() {\r\n  HttpModule.response.send(HttpModule.HttpStatus.HTTP_METHOD_NOT_ALLOWED, null);\r\n}<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-531d557 elementor-blockquote--skin-boxed elementor-blockquote--button-color-official elementor-widget elementor-widget-blockquote\" data-id=\"531d557\" data-element_type=\"widget\" data-widget_type=\"blockquote.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<blockquote class=\"elementor-blockquote\">\n\t\t\t<p class=\"elementor-blockquote__content\">\n\t\t\t\t\u26a0\ufe0f I would strongly advise you to log your actions through the <span style=\"font-weight:bold;\">console.log(...)<\/span> method as you cannot debug the script directly from VSCode. This is also one of the drawbacks of this method  it lacks debugging support, making it unfit for big projects.\t\t\t<\/p>\n\t\t\t\t\t<\/blockquote>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-44290fa elementor-widget elementor-widget-heading\" data-id=\"44290fa\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Deployment<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-510c7e9 elementor-widget elementor-widget-text-editor\" data-id=\"510c7e9\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You can deploy the script in the same way you would deploy a lightweight extension.\u00a0<\/p><p>To do so, simply create an <em><strong>ard<\/strong> <\/em>file (I called it <em><strong>myextension.ard<\/strong><\/em> but the name has no impact) next to your<em><strong> main.js<\/strong><\/em> file with the following content:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a02da26 elementor-widget elementor-widget-code-highlight\" data-id=\"a02da26\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-xml line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-xml\">\n\t\t\t\t\t<xmp><?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<AddOnRegData xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n    xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\"\r\n    SlientInstallation=\"\"\r\n    SlientUpgrade=\"\"\r\n    Partnernmsp=\"TheJonathanPapaCompany\"\r\n    SchemaVersion=\"3.0\"\r\n    Type=\"ServiceLayerScript\"\r\n    OnDemand=\"\"\r\n    OnPremise=\"\"\r\n    ExtName=\"OrderInvoice\"\r\n    ExtVersion=\"1.00\"\r\n    Contdata=\"sa\"\r\n    Partner=\"TheJonathanPapaCompany\"\r\n    DBType=\"Both\"\r\n    ClientType=\"S\">\r\n    <ServiceLayerScripts>\r\n        <Script Name=\"OrderInvoice\"\r\n            FileName=\"main.js\"><\/Script>\r\n    <\/ServiceLayerScripts>\r\n    <XApps>\r\n        <XApp Name=\"\"\r\n            Path=\"\"\r\n            FileName=\"\" \/>\r\n    <\/XApps>\r\n<\/AddOnRegData><\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-677d368 elementor-widget elementor-widget-text-editor\" data-id=\"677d368\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>At this point, the project should looke like that:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c5f37a9 elementor-widget elementor-widget-image\" data-id=\"c5f37a9\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/ardvsc.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"ardvsc\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6NzkxLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL2FyZHZzYy5wbmcifQ%3D%3D\">\n\t\t\t\t\t\t\t<img src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/elementor\/thumbs\/ardvsc-poi9tsa04snui56gx68mc8h8vzxup7wz5uvx2r7z28.png\" title=\"ardvsc\" alt=\"ardvsc\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d893fb3 elementor-widget elementor-widget-text-editor\" data-id=\"d893fb3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Finally, zip both the <em><strong>myextension<\/strong><strong>.ard<\/strong><\/em> and <strong><em>main.js<\/em><\/strong> files (do not put the sdk files into the archive).<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-05b57b2 elementor-widget elementor-widget-image\" data-id=\"05b57b2\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/slzip.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"slzip\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODEwLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL3NsemlwLnBuZyJ9\">\n\t\t\t\t\t\t\t<img src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/elementor\/thumbs\/slzip-poic5odca7xvefv1lund2a5booexrr6r0dm1bdgrby.png\" title=\"slzip\" alt=\"slzip\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9256d00 elementor-widget elementor-widget-text-editor\" data-id=\"9256d00\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>I called the archive <em><strong>myextension.zip<\/strong><\/em> but the file name has no importance for the rest of the process.<\/p><p>The resulting .zip archive can then be loaded through the Extension Manager (as you would load a lightweight extension add-on for SAP B1).<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-402edf7 elementor-widget elementor-widget-image\" data-id=\"402edf7\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/import-1.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"import-1\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODExLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL2ltcG9ydC0xLnBuZyJ9\">\n\t\t\t\t\t\t\t<img src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/elementor\/thumbs\/import-1-poic7qmqujrffopcq0jeb2d3sokvm24o8usx9tgst0.png\" title=\"import-1\" alt=\"import-1\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Importing the script - Uploading the .zip<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-86638d3 elementor-widget elementor-widget-text-editor\" data-id=\"86638d3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Don&rsquo;t forget to assign it to your favorite company (for me, that is \ud83c\udde6\ud83c\uddfa \u2764\ufe0f).<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d5cc441 elementor-widget elementor-widget-image\" data-id=\"d5cc441\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/import-3.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"import-3\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODE1LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL2ltcG9ydC0zLnBuZyJ9\">\n\t\t\t\t\t\t\t<img src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/elementor\/thumbs\/import-3-poiccevutw5r5vwyfj9m7dwm4njkvvomjzku6cjbv8.png\" title=\"import-3\" alt=\"import-3\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Importing the script - Company Assignment<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c65dd34 elementor-widget elementor-widget-heading\" data-id=\"c65dd34\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Testing<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9572d23 elementor-widget elementor-widget-text-editor\" data-id=\"9572d23\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You have to restart the service layer after importing the script.<\/p><p>Once this is done, you can easily test your script with Postman or any HTTP request creation tool.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0efffad elementor-widget elementor-widget-image\" data-id=\"0efffad\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2022\/05\/postmansuccess.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"postmansuccess\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6ODE2LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAyMlwvMDVcL3Bvc3RtYW5zdWNjZXNzLnBuZyJ9\">\n\t\t\t\t\t\t\t<img src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/elementor\/thumbs\/postmansuccess-poicgm7uux94za8z904bh9zr2yaenrmm5jes86kdeo.png\" title=\"postmansuccess\" alt=\"postmansuccess\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">It works!<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-9ce8c38 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"9ce8c38\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-06e0124\" data-id=\"06e0124\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a8f027a elementor-widget elementor-widget-heading\" data-id=\"a8f027a\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Advantages<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-36abe54 elementor-widget elementor-widget-text-editor\" data-id=\"36abe54\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li>As flexible as the DI-API can be! Beside, if you&rsquo;re familiar with it, you&rsquo;d pretty much find the same methods.<\/li><li>Adapted to Web API design.<\/li><li>Easy to deploy with the Extension Manager (same procedure as with add-ons).<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-7c4e1bc\" data-id=\"7c4e1bc\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-779f40f elementor-widget elementor-widget-heading\" data-id=\"779f40f\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Drawbacks<\/h4>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5f88006 elementor-widget elementor-widget-text-editor\" data-id=\"5f88006\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li>Limited to 10 operations per transaction (that&rsquo;s not <em>really<\/em> an issue, it&rsquo;s not likely that you would pack so many transactions together unless you&rsquo;re making data import).<\/li><li>Not debuggable (you have to deploy and check the logs to understand what&rsquo;s going on).<\/li><li>Javascript (it pretty much says it all).<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4b7a299 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4b7a299\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-65e5b99\" data-id=\"65e5b99\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5a2ddce elementor-widget elementor-widget-heading\" data-id=\"5a2ddce\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Conclusion<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-451d608 elementor-widget elementor-widget-text-editor\" data-id=\"451d608\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>So far, we&rsquo;ve seen 3 different methods of performing \u00ab\u00a0grouped operations\u00a0\u00bb:<\/p><ul><li>Via the DI-API by using both <span class=\"code\">StartTransaction()<\/span> and <span class=\"code\">EndTransaction()<\/span> methods<\/li><li>Via the Service Layer using the <span class=\"code\">\/$batch<\/span> endpoint.<ul><li>With non-coupled business objects (two independant items)<\/li><li>With coupled business objects (an order and its invoice)<\/li><\/ul><\/li><li>Via script extension of the Service Layer, using a javascript file.<\/li><\/ul><p>I hope this article gives you a better view of the options you have for building interfaces with SAP B1.\u00a0<\/p><p>Then, it&rsquo;s up to you to choose which method you&rsquo;ll use for your developement. Of course, every project is different. Just keep in mind that the DI-API is not adapted for web api while the service layer is. And that transactions come at a high cost whether they&rsquo;re being used from the DI-API or the Service Layer. \ud83d\ude09<\/p><p>Cheers \ud83e\udd19\ud83c\udffc<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Introduction In this tutorial, we will discuss the different approaches to use when packing multiple business operations together in SAP Business One&nbsp;and how we can avoid common mistakes that lead to incomplete processes. This article can be useful if: You&rsquo;re planning on building an interface for SAP B1 and want to know your options. You [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1019,"comment_status":"closed","ping_status":"open","sticky":true,"template":"","format":"standard","meta":{"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[10,23,14,22,15],"tags":[19,20,16,21,17,18,8],"_links":{"self":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/697"}],"collection":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/comments?post=697"}],"version-history":[{"count":10,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/697\/revisions"}],"predecessor-version":[{"id":1032,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/697\/revisions\/1032"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/media\/1019"}],"wp:attachment":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/media?parent=697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/categories?post=697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/tags?post=697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}