{"id":4756,"date":"2025-12-30T06:52:19","date_gmt":"2025-12-30T06:52:19","guid":{"rendered":"https:\/\/himbap.com\/blog\/?p=4756"},"modified":"2026-01-02T15:22:33","modified_gmt":"2026-01-02T15:22:33","slug":"filtering-price-lists-by-business-unit-in-d365ce","status":"publish","type":"post","link":"https:\/\/himbap.com\/blog\/?p=4756","title":{"rendered":"Filtering Price Lists by Business Unit in D365CE"},"content":{"rendered":"\n<p>In D365CE the <strong>Price List<\/strong> entity is an organization owned entity. This means that price lists are not owned by individual users or business units. Because of this ownership model, we can&#8217;t control visibility of using standard security roles. By default, all users in the organization can view all price lists, regardless of their business unit or role.<\/p>\n\n\n\n<p>Recently, I encountered a business requirement where users should be able to see only those price lists that are relevant to their own Business Unit. The expectation was that users from different business units should not have visibility into each other\u2019s price lists. Since this requirement could not be achieved using out-of-the-box security features, I implemented a <strong>RetrieveMultiple <\/strong>plugin on the Price List entity. This plugin dynamically filters the price list records at runtime based on the <strong>current user\u2019s Business Unit<\/strong>, ensuring that users only see the price lists they are allowed to access.<\/p>\n\n\n\n<p>To implement this I need to know name of the current user BU. One important point to consider is that we should not retrieve BU name using <strong>RetrieveMultiple <\/strong>plugin because it can trigger the same plugin again. This can result in an infinite loop. To avoid this, I used plugin configuration to pass this information.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<pre class=\"wp-block-code\"><code>if (context.MessageName != \"RetrieveMultiple\"||\ncontext.PrimaryEntityName != \"pricelevel\")\nreturn;\n\n        DK_PricelistId = GetStringValue(_unsecureConfig, \"DK\");\n\n        if (!context.InputParameters.Contains(\"Query\")) return;\nvar query = context.InputParameters&#91;\"Query\"];\n\n            if (query is QueryExpression qe)\n            {\n                qe.Criteria.AddCondition(\"pricelevelid\", ConditionOperator.Equal,DK_PricelistId);\n            }\n            else if (query is FetchExpression fe)\n            {\n                fe.Query = AddConditionToFetchXML(fe.Query, \"pricelevelid\", new Guid(DK_PricelistId).ToString());\n            } \n\n<\/code><\/pre>\n\n\n\n<p>To add condition in FetchXML we can use below method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private string AddConditionToFetchXML(string fetchXml, string attribute, string value)\n        {\n            var doc = XDocument.Parse(fetchXml);\n\n            var entity = doc.Root?.Element(\"entity\");\n            if (entity == null)\n                return fetchXml;\n\n            var filter = entity.Element(\"filter\");\n\n           if (filter == null)\n            {\n                filter = new XElement(\"filter\", new XAttribute(\"type\", \"and\"));\n                entity.Add(filter);\n            }\n            filter.Add(\n                new XElement(\"condition\",\n                    new XAttribute(\"attribute\", attribute),\n                    new XAttribute(\"operator\", \"eq\"),\n                    new XAttribute(\"value\", value)\n                )\n            );\n\n            return doc.ToString();\n        } <\/code><\/pre>\n\n\n\n<p>We can register this plugin on pre operation for pricelist entity and can pass configuration data like below under Unsecure Configuration. It will filtered pricelist based on the user BU.<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;configuration>\n&lt;setting name=\"DK\" value=\"86ca00df-ea0e-f011-9989-7c1e522a0c38\"\/>\n&lt;\/configuration><\/code><\/pre>\n\n\n\n<p>Once this logic is applied it will filter result like below:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/himbap.com\/blog\/wp-content\/uploads\/2026\/01\/onlydkk.png\"><img decoding=\"async\" loading=\"lazy\" width=\"470\" height=\"228\" src=\"https:\/\/himbap.com\/blog\/wp-content\/uploads\/2026\/01\/onlydkk.png\" alt=\"\" class=\"wp-image-4760\" srcset=\"https:\/\/himbap.com\/blog\/wp-content\/uploads\/2026\/01\/onlydkk.png 470w, https:\/\/himbap.com\/blog\/wp-content\/uploads\/2026\/01\/onlydkk-300x146.png 300w\" sizes=\"(max-width: 470px) 100vw, 470px\" \/><\/a><\/figure><\/div>\n\n\n<p>While moving this to another environment we can update GUID.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Summary<\/strong><\/h2>\n\n\n\n<p>This is how we can use RetrieveMultiple plugin to filter query to modify result on views.<\/p>\n\n\n\n<p>Hope it will help someone!!<br><strong>Keep learning and Keep Sharing!!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In D365CE the Price List entity is an organization owned entity. This means that price lists are not owned by individual users or business units. Because of this ownership model, we can&#8217;t control visibility of using standard security roles. By default, all users in the organization can view all price lists, regardless of their business unit or role. Recently, I&#8230; <a href=\"https:\/\/himbap.com\/blog\/?p=4756\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":4757,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[402,522,5,8,275,20],"tags":[1150,1153,1151,1152],"_links":{"self":[{"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4756"}],"collection":[{"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4756"}],"version-history":[{"count":3,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4756\/revisions"}],"predecessor-version":[{"id":4761,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4756\/revisions\/4761"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=\/wp\/v2\/media\/4757"}],"wp:attachment":[{"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4756"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4756"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/himbap.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4756"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}