Category Archives: JavaScript
How We Built a Real-Time Lightweight Financial Statement Reporting Experience Directly Inside D365 PO for a Texas-Based Cybersecurity Firm
How We Built a Real-Time Lightweight Financial Statement Reporting Experience Directly Inside Microsoft Dynamics 365 Project Operations Summary Designed and deployed a lightweight, real-time financial statement reporting solution directly inside Microsoft Dynamics 365 Project Operations for a Texas-based Cybersecurity & AI Business Solutions firm. Eliminated dependency on heavy paginated reporting and large-scale Power BI datasets for operational financial visibility. Built an interactive HTML + JavaScript reporting framework embedded natively within Dynamics 365 CRM. Enabled dynamic filtering, instant report rendering, and printable customer-ready statements directly from the CRM interface. Introduced popup-based full-screen report rendering for detailed review and print-ready output without leaving Dynamics 365. Integrated funding balances, allocations, transactions, installment schedules, and financial snapshots into a single operational reporting experience. Reduced reporting development complexity, minimized data transformation overhead, and improved scalability compared to traditional BI-heavy architectures. Created a highly maintainable reporting model that scales efficiently as operational datasets grow without introducing significant Power BI licensing or performance constraints. Table of Contents Introduction The Business Problem The Solution Architecture Real-Time CRM-Native Reporting Lightweight Front-End Reporting Framework Popup-Based Printable Report Experience Data Model and Reporting Components Design Principles Business Impact Why This Approach Worked FAQs Conclusion 1. Introduction As organizations scale, operational reporting often becomes increasingly difficult to maintain. For a Texas-based Cybersecurity & AI Business Solutions firm operating on Microsoft Dynamics 365 Project Operations, this challenge became especially visible in financial agreement tracking and customer funding visibility. The business already had access to reporting platforms such as Power BI and paginated reports. However, these approaches introduced several operational problems: Long development cycles Heavy data-cleaning requirements Complex transformation pipelines Delayed visibility into operational data Increasing licensing costs as datasets expanded Slow report rendering for operational users Dependency on external reporting infrastructure Instead of another external BI layer, the organization wanted a lightweight operational reporting experience directly inside Dynamics 365 CRM itself. The Goal: Build a real-time, CRM-native financial reporting experience that renders instantly, supports dynamic filtering, enables printing, and scales without heavy BI infrastructure. 2. The Business Problem The organization manages multiple long-running service agreements, funding allocations, installment schedules, and customer financial balances across cybersecurity services, managed services, and AI solution engagements. Operational users needed a consolidated statement experience that could answer questions such as: What is the customerās current available balance? Which transactions impacted the balance during a selected period? Which allocations are currently active? How much funding has been consumed vs allocated? Which installments are pending, paid, or overdue? What does the latest funding snapshot look like? Can the report be reviewed and printed directly from CRM? Paginated Reporting Limitations Increasing query complexity Performance degradation with larger datasets Heavy formatting maintenance Limited interactivity Rigid deployment cycles Power BI Challenges Significant Power Query transformations Data-cleaning pipelines Incremental refresh considerations Dataset refresh latency Licensing growth with scale Overengineering for transactional operational reporting 3. The Solution Architecture The reporting framework was designed as a native Dynamics 365 embedded reporting experience using: HTML Web Resources JavaScript Dynamics 365 Web API Native CRM navigation APIs Real-time entity retrieval Popup-based print rendering Embedded Operational Report Apply filters Select funding records Choose reporting periods Generate statements instantly Navigate operational financial data Popup Print Report Detailed review Executive presentation Customer-facing statements Printing and PDF generation 4. Real-Time CRM-Native Reporting One of the most important architectural decisions was avoiding external data replication entirely. Instead of pushing transactional data into a separate reporting warehouse, the report retrieved data directly from Dynamics 365 using the native Web API. Real-time visibility Zero synchronization lag Reduced infrastructure complexity Lower maintenance overhead Faster deployment cycles Everything rendered on demand inside the CRM session itself. 5. Lightweight Front-End Reporting Framework The reporting experience was intentionally designed to behave more like a modern application than a traditional report. Dynamic Filter Bar Users could dynamically filter reports using: This Month Last Month This Quarter Current Year Custom Date Ranges Funding Status Funding Selection The report regenerated instantly without page reloads. Responsive Report Rendering The reporting layout dynamically populated: Account Summary Transaction Details Allocation Summary Installment Details Detailed Account Summary Each section rendered independently based on live API responses. Intelligent Empty-State Handling Instead of showing blank tables or errors, the framework displayed contextual empty-state messaging such as: āNo transactions during this statement periodā āNo active allocationsā āNo installment details availableā This significantly improved usability for operational teams. 6. Popup-Based Printable Report Experience A major requirement was enabling users to thoroughly review and print reports directly from CRM. To solve this, the solution introduced a dedicated popup rendering architecture. Users could click: āExpand Reportā This launched a fullscreen popup using Dynamics 365 navigation APIs with: Large-format rendering Print-optimized layout Full customer statement formatting Multi-page support Consistent branding Printable tables Customer reference guides The popup approach delivered several advantages: Better readability Cleaner print formatting Improved executive review experience Isolation from CRM form clutter Easier PDF generation Most importantly, the popup still worked entirely against live CRM data. 7. Data Model and Reporting Components The report consolidated multiple operational areas into a single experience. Account Summary Provided a high-level balance overview including: Balance Forward Total Credits Total Debits Closing Balance This gave immediate visibility into customer financial standing. Transaction Details Displayed detailed running balance activity including: Document date Transaction description Service type Credits Debits Running balance Transactions dynamically recalculated balances during rendering. Allocation Summary Tracked funding allocation activity including: Allocated funds Consumed funds Remaining balance Allocation status Returned allocations were handled separately with custom date logic. Installment Tracking Displayed installment lifecycle visibility including: Invoice dates Due dates Payment dates Payment terms Installment status The report intelligently handled future-dated payments and pending statuses. Detailed Funding Snapshot Displayed operational funding metrics including: Starting Balance Contracted Funds Total Budgeted Funds Collected Funds Used Funding Available Funds Allocated Funds Unallocated Funds This created a complete operational funding overview within a single screen. 8. Design Principles Several architectural principles guided the solution. Real-Time Over Batch Processing Operational reporting should reflect current business activity immediately. The solution avoided overnight refresh cycles entirely. Lightweight Over Heavy BI Not … Continue reading How We Built a Real-Time Lightweight Financial Statement Reporting Experience Directly Inside D365 PO for a Texas-Based Cybersecurity Firm
Share Story :
Building a Controlled Booking-to-Time Entry Import Framework Inside Dynamics 365 Project Operations for Texas-Based Operational Security & Cybersecurity Firms
Building a Controlled Booking-to-Time Entry Import Framework Inside Dynamics 365 Project Operations Summary Two Texas-based firms ā one in Cybersecurity, another in Operational Security ā required a streamlined and controlled Time Entry (TE) creation process inside Dynamics 365 Project Operations. Native D365 Project Operations limitations around Project Task visibility, booking-driven TE creation, and inconsistent resource submissions created operational inefficiencies. A fully customized solution was implemented directly inside Dynamics 365 CRM using HTML Web Resources, JavaScript, Dataverse Web API, Ribbon Enable Rules, and custom plugins. The solution centralized TE creation under Project Managers and Project Approvers, enabling controlled and secure booking-based TE management. A custom booking import framework dynamically surfaced only authorized projects and resources based on Project Approver relationships. Custom plugin logic and Resource Assignmentābased task resolution automated Project Task mapping for accurate Time Entry creation. Key capabilities delivered included controlled booking imports, role-based visibility, automated task association, external comments support, and bulk TE creation. Dynamic filtering ensured Project Managers could only access resources and bookings associated with projects they were authorized to manage. The entire experience operated natively inside Dynamics 365 Project Operations without external portals, Power Apps screens, or third-party applications. The implementation reduced manual effort, improved TE submission reliability, increased operational flexibility, and enabled more accurate tracking of actual project work. Table of Contents Introduction The Business Problem & Pain Points The Solution Architecture Implementation Design Principles Business Impact Why This Approach Worked FAQs Conclusion 1 Introduction Two Texas-based firms operating in the Cybersecurity and Operational Security space relied heavily on Dynamics 365 Project Operations for project delivery tracking, resource management, and operational execution. As project operations scaled, Project Managers and Project Approvers required a faster and more controlled mechanism for creating Time Entries (TEs) directly from resource bookings. The organizations needed a solution that could simplify booking imports, improve Project Task mapping, enforce role-based visibility, and reduce the dependency on individual resources for manual TE submissions. Operationally, Project Managers were often responsible for validating and entering actual work performed, making the standard TE process inefficient and time-consuming. Key Challenges Standard Dynamics 365 Project Operations behavior did not fully support project-task-aware Time Entry creation from bookings. Project Task values were not consistently available across Resource Requirements and bookings in several PO environments. Resource-driven TE submission resulted in inconsistent and delayed operational reporting. Project Managers lacked centralized visibility and controlled access to resource bookings across approved projects. Native booking import and TE creation workflows lacked flexibility for operational governance and scalability. Goals of the Solution Centralize Time Entry creation under Project Managers and Project Approvers. Enable controlled booking imports with role-based project visibility. Automate Project Task association during TE creation. Allow bulk creation of booking-driven Time Entries directly inside CRM. Improve operational accuracy, flexibility, and governance without relying on external applications or custom portals. 2 The Business Problem & Pain Points 1. Native Booking-to-Time Entry Limitations Standard Dynamics 365 Project Operations behavior did not consistently expose Project Task information through Resource Requirements and Bookings. This created gaps in task-aware Time Entry creation and forced users to manually reconstruct operational context during the TE process. 2. Lack of Controlled Booking Visibility Default system behavior provided broader booking visibility than operationally required. The organizations needed a controlled access model where only designated Project Managers and Project Approvers could view and manage booking imports for authorized projects. 3. High Manual Effort in Time Entry Creation Project Managers and operational teams spent significant time manually entering project references, tasks, durations, and external comments for each Time Entry. This increased administrative overhead and reduced operational efficiency. 4. Inconsistent Resource-Driven Submission Process The organizations faced reliability challenges with resource-submitted Time Entries, leading to delays, missing entries, and inconsistencies in operational reporting. Project Managers required centralized ownership over TE creation to ensure accurate work tracking. 5. Fragmented User Experience Users were required to navigate across multiple Dynamics 365 screens and entities to complete routine booking import and Time Entry operations, making the process cumbersome and inefficient for daily operational usage. 6. Scalability and Maintainability Concerns The firms required a lightweight and scalable solution that could operate natively within Dynamics 365 Project Operations without introducing unnecessary Power Apps layers, external portals, or high-maintenance custom applications. 3 The Solution Architecture Architecture Diagram and Flow Figure: Complete Frontend – Backend behaviour of the TE Automation Module. Dynamics 365 Ribbon Workbench A custom “Import Resource Bookings” ribbon action was introduced to provide controlled access to the booking import process only for authorized Project Managers and Project Approvers. JavaScript + Dataverse Web API JavaScript and Dataverse Web API were used to handle dynamic project filtering, approver validation, booking retrieval, task mapping, and automated Time Entry creation directly inside CRM. HTML Web Resources Two custom HTML-based interfaces were developed: Resource Selection Interface ā controlled resource visibility and selection Booking Import & TE Creation Interface ā booking imports, task selection, external comments, and bulk Time Entry creation Dataverse Plugin Layer A lightweight custom C# plugin was implemented to support Project Task resolution, task validation, and booking-to-Time Entry automation scenarios not fully supported natively in Dynamics 365 Project Operations. Dataverse Entities Involved The solution leveraged multiple Project Operations entities: msdyn_project msdyn_projectteam msdyn_resourceassignment msdyn_projecttask bookableresource msdyn_resourcerequirement bookableresourcebooking msdyn_timeentry Together, these entities enabled secure, project-aware, and task-aware operational workflows directly inside Dynamics 365 CRM. Entity Relationships Figure: Relationships and associations of the involved entities. 4 Implementation 1. Role-Controlled Ribbon Visibility A custom ribbon action was implemented to ensure only authorized Project Managers and Project Approvers could access the booking import functionality. Visibility was dynamically controlled based on project approval relationships inside Dynamics 365. Figure: Case 1: When Logged in as a Project Approver/Manager. Figure: Case 2: When NOT Logged in as a Project Approver/Manager. 2. Resource Selection Experience A custom resource selection interface was developed to display only eligible resources associated with projects managed by the logged-in approver. This provided secure and simplified operational visibility. Figure: Bookable Resource Selection from a list of Active Bookable Resources, which are under any Project, where the current … Continue reading Building a Controlled Booking-to-Time Entry Import Framework Inside Dynamics 365 Project Operations for Texas-Based Operational Security & Cybersecurity Firms
Share Story :
Transforming Return Logistics for a USA Manufacturer: Automating Shipment Processing with Dynamics 365 Customer Service
Summary This blog highlights the integration of Microsoft Dynamics 365 Customer Service Hub with FedEx Shipping Manager to handle automated email return shipments for a consumer electronic appliances company based in Massachusetts, USA. In the original process, customer service representatives were required to manually register each return shipment through the FedEx Shipping Manager portal. This process involved copying customer details, creating shipments, generating labels, and capturing tracking numbers ā a workflow that typically required 20ā30 minutes per request. The integration project automated the entire return shipment process directly within the Dynamics 365 Customer Service Hub. With a single click, the system now registers the shipment using FedEx Shipment APIs, generates a return label, captures the tracking number, and updates the case record automatically. This innovation eliminated the need for agents to switch between systems and reduced shipment registration time from 20ā30 minutes to just a few seconds, significantly improving operational efficiency and the overall customer service experience. This blog explains: 1] The operational challenges caused by manual shipment registration. 2] How Dynamics 365 Customer Service Hub was integrated with FedEx Shipping Manager. 3] The functional workflow used to automate shipment creation. 4] How customer service representatives trigger shipments directly from CRM. 5] The business impact achieved through automation and system integration. Table of Contents 1. Customer Scenario 2. Solution Overview 3. Functional Implementation Approach 4. Email Return Label Experience 5. Handling Complex Data Automatically 6. Business Impact 7. Preview Video 8. Final Thoughts Customer Scenario A Massachusetts-based consumer appliance manufacturer known for building innovative kitchen technology was experiencing a growing operational challenge in its customer service operations. As demand for its products increased across major retail channels, the number of customer support cases related to product returns and replacements also grew significantly. The companyās customer support team handled all service requests through Microsoft Dynamics 365 Customer Service. However, when a product needed to be returned for inspection, replacement, or warranty evaluation, agents were required to manually create a shipment in FedEx Ship Manager. This manual process involved several steps: 1] Opening the customer case in the CRM system 2] Copying customer information and shipping details 3] Logging into the FedEx portal 4] Registering the shipment manually 5] Generating a return label 6] Capturing the tracking number 7] Returning to CRM to update the case Each shipment registration typically took 20ā30 minutes. When hundreds of return requests were processed weekly, this created several operational challenges: 1] Agents constantly switched between multiple systems 2] Manual data entry increased the risk of errors 3] Customer response times increased, leading to customer resentment 4] Tracking information was not always immediately available in the case record The organization needed a more efficient way to handle returns while keeping the entire process inside their CRM platform. Solution Overview To streamline the returns process, I implemented an integration between Microsoft Dynamics 365 Customer Service and FedEx shipping manager services. The goal was simple: Allow customer service representatives to generate a return shipment directly from the case record with a single click. Instead of navigating to the separate external shipping portal, agents can now initiate a return shipment directly from the CRM case page. Once triggered, the system automatically handles the entire shipment (Email/Return/Label) registration process. With this solution in place, the workflow now looks like this: A customer contacts support regarding a product return via their website, which registers an associated Case record in D365 Case Management (via existing case automation). The support agent opens the case in Dynamics 365. A āCreate Return Shipmentā button becomes available when the case meets the required conditions, e.g., Case Stage, RMA availability, Region of Customer, etc., thus validating and restricting shipment privileges. With one click, the system registers the shipment with FedEx (via appropriate FedEx Shipment APIs, as per customer requirements). The shipment tracking number is automatically captured and stored in the case record. This tracking number is useful for the customer support team as well as the customer to check the progress of the shipment on the FedEx Shipping Manager portal. The customer receives an email return label that they can print and attach to their package. FedEx Email Return Shipment Process Flow This transformation reduced a 20ā30 minute process to just a few seconds. Functional Implementation Approach The implementation focused on simplifying the experience for customer service agents while maintaining strict control over when and how shipments could be created. Intelligent Shipment Trigger Visibility Within the CRM case interface, the return shipment button appears only when specific conditions are met. This ensures that shipments are created only for valid return scenarios. Examples of conditions include: The case must have an approved return authorization The case must be in an appropriate service stage The customer address must be eligible for shipment Required customer information must be available Example: Return Shipment Trigger inside Dynamics 365 Customer Service Hub By embedding these conditions into the CRM interface, agents are guided through the correct service workflow without needing to remember complex procedures. Automated Shipment Creation Once the button is clicked, the system automatically gathers key information from the case record, such as: Customer details Shipping address Product description Return authorization number Contact phone number This information is then used to register the shipment through the FedEx shipping system. The system generates: A unique shipment tracking number A return shipment registration A digital return label The warehouse where the shipment would reach based on the product and end consumer requirement ā e.g., return, replacement, or repair of the product Example: A Successful Return Shipment to a specific warehouse. Example: Tracking a Return Shipment using the Tracking No. updated on D365 Customer Service Hub. Example: The FedEx Shipping Manager for Tracking the Integrated Shipments. The tracking number is immediately written back to the case record in Microsoft Dynamics 365 Customer Service, ensuring that support agents can track the return shipment without leaving the case. Email Return Label Experience After the shipment is registered, the customer automatically receives an email containing their return label. … Continue reading Transforming Return Logistics for a USA Manufacturer: Automating Shipment Processing with Dynamics 365 Customer Service
Share Story :
Browser-Level State Retention in Dynamics 365 CRM: Improving Performance & UX with Session Storage
Dynamics 365 model-driven apps are excellent at storing business data, but not every piece of information belongs in Dataverse. A common design folly is using Dataverse fields to store temporary UI state-things like selected views, filters, or user navigation preferences. While this works technically, it introduces unnecessary performance overhead and can create incorrect behavior in multi-user environments. In this blog, Iāll focus on browser-level retention of CRM UI data using “sessionStorage“, using subgrid view retention as a practical example for a technology consulting and cybersecurity services firm based in Houston, Texas, USA, specializing in modern digital transformation and enterprise security solutions. The Real Problem: UI State vs Business Data Letās separate concerns clearly: Type Example Where it should live Business data Status, owner, amounts Dataverse UI state Selected view, filter, scroll position Browser Subgrid views fall squarely into the UI state category. Scenario: Subgrid View Resetting on Navigation Users reported the following behavior: This breaks user workflow, especially for records that users revisit frequently. Possible Solution: Persisting UI State in Dataverse (Original Approach) This would attempt to fix it by storing the selected subgrid view GUID in a Dataverse field on the parent record. How It Works Why this might look reasonable The Hidden Problems 1] Slower Form Execution 2] Data Model Pollution 3] Incorrect Multi-User Behavior 4] Scalability Issues In short, Dataverse was doing work it should never have been asked to do. Workaround to this Approach: Keep UI State in the Browser for that session, But practically: The selected subgrid view belongs to the userās session, not the record. Once that boundary is respected, the solution becomes much cleaner. Practical Solution: Browser Session Storage (Improved Approach) Instead of persisting view selection in Dataverse, we store it locally in the browser using sessionStorage. sessionStorage is part of the Web Storage API, which provides a way to store key-value pairs in a web browser. Unlike localStorage, which persists data even after the browser is closed, sessionStorage is designed to store data only for the duration of a single session. This means that the data is available as long as the tab or window is open, and it is cleared when the tab or window is closed. Why Session Storage? How the Improved Solution Works 1. Store the View Locally on Subgrid Change 2. Restore the View on Form/Grid Load This ensures that when the user revisits the form, the subgrid opens exactly where they left off. Why This Approach Is Superior 1] Faster Execution 2] Correct User Experience 3] Clean Architecture 4] Zero Backend Impact When to Use Browser-Level Retention Use this pattern when: Examples: To conclude, not all data deserves to live in Dataverse. When you store UI state in the browser instead of the database, you gain: Subgrid view retention is just one example-but the principle applies broadly across Dynamics 365 customizations. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com
Share Story :
Seamlessly Switching Lead-Based BPFs After Qualification in Dynamics 365 CRM
In Microsoft Dynamics 365 CRM, Business Process Flows (BPFs) are powerful tools that guide users through defined business stages. However, when working with Lead-based BPFs that persist into Opportunity, certain platform limitations surface-especially when multiple Lead-rooted BPFs are involved. This blog walks through a real-world challenge I encountered while working with a Houston-based technology consulting and cybersecurity services firm. The firm specializes in modern digital transformation and enterprise security solutions. I explore issues with Lead ā Opportunity Business Process Flow (BPF) switching, explain why the out-of-the-box behavior falls short, and detail how I designed a robust client-side and server-side solution to safely and reliably switch BPFs-even after a Lead has already been qualified. How BPFs Work (Quick Recap) It ideally won’t allow a switch, either via brute forcing via client side or server side as – The Problem In my scenario: The Challenge Once a Lead is qualified: This is non-intuitive, error-prone, and inefficient, especially considering the manual effort that goes into it. Solution Overview I implemented a guided, safe, and reversible BPF switching mechanism that: High-Level Architecture This solution uses: Step-by-Step Methodology 1. Entry Point: Opportunity Ribbon Button A custom ribbon button on the Opportunity form: These fields act as a controlled handshake between Opportunity and Lead. 2. Lead OnLoad: Controlled Trigger Execution On Lead form load: if (diffSeconds > 20) { return;} Xrm.WebApi.updateRecord(“lead”, formContext.data.entity.getId(), { cf_shouldtrigger: false}); This ensures: 3. Identifying and Aborting the Existing BPF Before switching: var activeProcess = formContext.data.process.getActiveProcess(); Xrm.WebApi.updateRecord(bpfEntityName,result.entities[0].businessprocessflowinstanceid,{statecode: 1, // Inactivestatuscode: 3 // Aborted}); This is a critical stepāwithout aborting the old instance, Dynamics can behave unpredictably. 4. Switching the UI BPF After aborting: 5. Handling BPF Instance Creation (First-Time Switch Logic) The solution explicitly checks: If it exists: If it does NOT exist (first switch): This dual-path logic makes the solution idempotent and reusable. 6. Server-Side Plugin: Persisting the Truth A plugin ensures that: // Identify BPF typebool isNewBpf = (context.PrimaryEntityName == “new_bpf_entity”); // Resolve related LeadGuid leadId = isNewBpf? ((EntityReference)target[“bpf_leadid”]).Id: ((EntityReference)target[“leadid”]).Id; // Retrieve related Opportunity via LeadEntity opportunity = GetOpportunityByLead(service, leadId); // Determine stages and pathstring qualifyStageId = isNewBpf ? NEW_QUALIFY_STAGE : OLD_QUALIFY_STAGE;string finalStageId = isNewBpf ? NEW_FINAL_STAGE : OLD_FINAL_STAGE;string traversedPath =START_STAGE + “,” + qualifyStageId + “,” + finalStageId; // PATCH 1 ā Qualify stageservice.Update(new Entity(target.LogicalName, target.Id){[“activestageid”] = new EntityReference(“processstage”, new Guid(qualifyStageId)),[“traversedpath”] = START_STAGE + “,” + qualifyStageId}); // PATCH 2 ā Final stage + Opportunity bindservice.Update(new Entity(target.LogicalName, target.Id){[“activestageid”] = new EntityReference(“processstage”, new Guid(finalStageId)),[“traversedpath”] = traversedPath,[isNewBpf ? “bpf_opportunityid” : “opportunityid”] =new EntityReference(“opportunity”, opportunity.Id)}); // Mark Lead as successfully processedservice.Update(new Entity(“lead”, leadId){[“cf_pluginsuccess”] = new OptionSetValue(1) // Yes}); This guarantees data consistency and auditability. 7. Final UI Sync & Redirect After successful completion: Xrm.Navigation.openForm({ entityName: “opportunity”, entityId: opportunityId }); From the userās perspective: āI clicked a button, confirmed the switch, and landed back in my Opportunityādone.ā Why This Solution Works ā Respects Dynamics 365 BPF constraintsā Prevents orphaned or conflicting BPF instancesā Handles first-time and repeat switchesā Ensures server-side persistenceā Minimal user disruptionā Fully reversible Most importantly, it bridges the gap between platform limitations and real business needs. Dynamics 365 BPFs are powerful-but when multiple Lead-rooted processes coexist, manual switching is not enough. This solution demonstrates how: can be combined to deliver a seamless, enterprise-grade experience without unsupported hacks. If youāre facing similar challenges with Lead ā Opportunity BPF transitions, this pattern can be adapted and reused with confidence. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com
Share Story :
Filtering Dynamics 365 Subgrids Without Relationships: A JavaScript-Only Approach Using setFilterXml
In Microsoft Dynamics 365, subgrids are a powerful way to display related records on a form. But what happens when: Out-of-the-box, Dynamics 365 doesnāt give us many options here. We can select a view, but we cannot apply dynamic filters unless the entities are directly related or the criteria already exist in the viewās FetchXML. This is where the JavaScript setFilterXml() API becomes a life-saver. In this article, Iāll show you how to filter a subgrid dynamically using JavaScript ā even when the subgridās entity is completely unrelated to the main form entity. Use Case Imagine your form has a field called Name, and you want to filter the subgrid so that it shows only records whose Name begins with the same prefix. But: As there are also records, where the lookup column might need to be empty on purpose, which further would break relationship based filtering in the subgrid. OOB? Impossible. With JavaScript? Totally doable. How the JS based subgrid filtering works In Dynamics 365, subgrids are rendered as independent UI components inside the form. Even though the form loads first, subgrids load asynchronously in the background, which means: The form and its fields may already be available, but the subgrid control might not yet exist, so trying to apply a filter immediately on form load will fail. Here is the basic structure of a JS Function to perform Subgrid filtering – This control represents the interactive UI component that displays the records for the view.It gives you programmatic access to:-> Set filters-> Refresh the grid-> Access its view ID-> Handle events (in some versions) However, because subgrids load later than the form, this line may return null the first several times. If you proceed at that point, your script will break.So we implement a retry pattern: If the subgrid is not ready, wait 100ms -> Try again -> Repeat until the control becomes availableThis guarantees that our next steps run only when the subgrid is fully loaded. var oAnnualTCVTargetGridFilter = oAnnualTCVTargetGridFilter || {}; oAnnualTCVTargetGridFilter.filterSubgrid = function(executionContext) {var formContext = executionContext.getFormContext(); }; To make sure the filter is applied correctly, we follow a three-step workflow: 1. Retry Until the Subgrid Control Is Loaded (setTimeout) – When the script runs, we attempt to retrieve the subgrid control using: var subgrid = formContext.getControl(“tcvtargets”); 2. Apply the Filter (setFilterXml()) – Once the subgrid control is found, we can safely apply a filter. Then we can apply our filtering logic, and utilize it in the FetchXML Query: -> Read the field Name (cf_name) from the main form & design a logic -> Construct a FetchXML <filter> element -> Passing this XML to the subgrid using: This tells Dynamics 365 to apply an additional filter on top of the existing view used by the subgrid. A few important things to note: If the cf_name field is empty, we instead apply a special filter that returns no rows. This ensures the grid displays only relevant and context-driven data. 3. Refresh the Subgrid (subgrid.refresh()) – After applying the filter XML, the subgrid must be refreshed: Without this call, Dynamics will not re-run the query, meaning your filter won’t take effect until the user manually refreshes the subgrid. Refreshing forces the system to: -> Re-query data using the combined view FetchXML + your custom filter -> Re-render the grid -> Display the filtered results immediately This gives the user a seamless, dynamic experience where the subgrid shows exactly the records that match the context. JS + FetchXML based filtering in action – Without filtering :- With filtering :- Key Advantages of This Approach Works Even When No Relationship Exists Possibility to filter a subgrid even if the target entity has no direct link to the formās main entity. This is extremely useful in cases where the relationship must remain optional or intentionally unpopulated. Enables Dynamic, Contextual Filtering We can design filtering logic on the form field values, user selections, or business rules. Filtering on Fields Not Included in the View Since the filtering logic is applied client-side, there is no need to modify or clone the system view just to include filterable fields. Bypasses Limitations of Lookup-Based Relation Filtering This method works even when the lookup column is intentionally left empty, which is a scenario where OOB relationship-based filtering fails. More Flexible Than Traditional View Editing You can apply advanced logic such as prefix matching, conditional filters, or dynamic rangesāthings not possible using standard UI-only configuration. To conclude, filtering subgrids dynamically in Dynamics 365 is not something the platform supports out-of-the-box- especially when the entities are unrelated or when the filter criteria doesnāt exist in the subgridās original view. However, with a small amount of JavaScript and the setFilterXml() API, you gain complete control over what data appears inside a sub grid, purely based on the context passed from the main form. I Hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudFronts.com.
Share Story :
Auto Refresh Subgrid in Dynamics 365 CRM Based on Changes in Another Subgrid
In Dynamics 365 CRM implementations, subgrids are used extensively to show related records within the main form. But what if you want Subgrid B to automatically refresh whenever a new record is added to Subgrid A, especially when that record triggers some automation like a Power Automate flow or a plugin that creates or updates related data? In this blog, Iāll walk you through how to make one subgrid refresh when another subgrid is updated ā a common real-world scenario that enhances user experience without needing a full form refresh. Letās say you have two subgrids on your form: Whenever a new record is added in the Chargeable Categories subgrid, a Power Automate flow or backend logic creates corresponding records in Order Line Categories. However, these new records are not immediately visible in the second subgrid unless the user manually refreshes the entire form or clicks on the refresh icon. This can be confusing or frustrating for end-users. Solution Overview To solve this, weāll use JavaScript to listen for changes in Subgrid A and automatically refresh Subgrid B once something is added. Hereās the high-level approach: Implementation Steps 1. Create the JavaScript Web Resource Create a new JS web resource and add the following code: How It Works To conclude, this simple yet effective approach ensures a smoother user experience by reflecting backend changes instantly without needing to manually refresh the entire form. Itās particularly helpful when automations or plugins create or update related records that must appear in real-time. By combining JavaScript with Dynamicsā form controls, you can add polish and usability to your applications without heavy customization. I hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfronts.com.
Share Story :
Disqualify Single or Multiple Quotes in Dynamics 365 with One Click!
If youāve ever needed to mark multiple quotes as lost in Dynamics 365, you know the default āClose Quoteā dialog can be slow and repetitive.In my recent project, the sales team wanted a faster way, one click from the main Quotes view, to disqualify single or multiple quotes, without opening each one or clicking through extra prompts. Using the out-of-the-box CloseQuote action, a small JavaScript function, and a custom Ribbon Workbench button, I built exactly that. Hereās how. Why I Needed This Our sales team often manages multiple quotes at once. The standard process meant: It was time-consuming, especially for bulk operations. We needed a quick, grid-based action that would: Step 1 ā Using the OOB CloseQuote Action Dynamics 365 provides a built-in CloseQuote bound action that changes the state and status of a quote to closed. Instead of creating a custom action, I decided to call this OOB action directly from JavaScript. Step 2 ā JavaScript to Call the OOB Action Hereās the function I wrote to handle both single and multiple quotes: Step 3 ā Adding the Ribbon Button in Ribbon Workbench Now, the button will be available directly on the Quotes view. Step 4 ā Testing the Feature This reduced what was previously a multi-click, per-record task into a single action for any number of quotes. Why This Works Well To conclude, by combining the OOB Close Quote action with Ribbon Workbench, I could instantly disqualify quotes from the main grid, saving hours over the course of a month. If youāre looking to simplify repetitive processes in Dynamics 365, start by exploring whatās already available out of the box, then add just enough customization to make it your own. š Need help implementing a custom button or enhancing your Dynamics 365 sales process? At CloudFronts, we help businesses design and implement scalable, user-friendly solutions that streamline daily operations and improve adoption. Whether itās customizing Ribbon Workbench, integrating OOB actions, or building tailored automation, our team can make it happen. š© Reach out to us at transform@cloudfronts.com and letās discuss how we can optimize your Dynamics 365 environment.
Share Story :
Power Pages + Power Automate: Retrieve SharePoint Files via HTTP Trigger Flow
When building a Power Pages site to fetch SharePoint files, I initially relied on the official Power Pages flow triggerā“When Power Pages calls a flow.” However, the flow didnāt trigger reliably when initiated from the site. Despite proper configurations, the trigger wouldnāt execute consistently, leading to broken file fetch operations. To overcome this, I replaced the unreliable trigger with a Power Automate flow using an HTTP request trigger. This method allowed me to invoke the flow through a JavaScript function executed on page load, passing the required record ID dynamically. The HTTP approach not only worked reliably but also gave me more control over the request and response. This blog post outlines that workaround, from setting up the HTTP-triggered flow to integrating it seamlessly with Power Pages. Background and the Problem Power Pages provides a native trigger to call Power Automate flows. While ideal in theory, this approach often fails in practice due to: After spending time investigating these issues without consistent results, I decided to switch to a more controlled and universally reliable method using a HTTP trigger. My Workaround ā HTTP Trigger Flow Power Automate Flow Setup: Trigger:Start with the āWhen an HTTP request is receivedā trigger. Define the request schema to accept a recordIdā in this case, an orderId. Compose (Request Variables):Add a Compose action to extract the incoming ID. List Rows ā Document Locations:Use Dataverse ā List rows to retrieve the SharePoint Document Location related to the Order (based on the passed orderId). This assumes your files are stored in folders linked to Dataverse records. Condition ā Check If Folder Exists:Use a Condition to check if any document location was found: If record exists ā proceed, If no records found ā terminate the flow (folder doesnāt exist). Compose ā Relative URL: Compose ā Folder Path:Combine the folder path: Get Files (SharePoint):Use the SharePoint Get files (properties only) action with the dynamic path set to the DocumentPath variable. Return Response:Format the SharePoint file metadata (Name, Link, Type) and send it back using the Response action. JavaScript (Executed on Page Load) Why This Works: Pros: Cons: To conclude, if youāve faced reliability issues with native Power Pages flow triggers, the HTTP request method can be a game-changer. It enabled me to deliver a seamless experience for retrieving SharePoint files, and it can do the same for your project. In future iterations, I plan to enhance this by adding bearer token authentication and caching metadata for even faster performance. Want to integrate Power Automate flows reliably with Power Pages? Reach out to CloudFrontsāwe help businesses implement scalable, reliable Power Platform solutions every day. You can contact us directly at transform@cloudfronts.com.
Share Story :
Comparing Asynchronous Patterns in C# and JavaScript
Asynchronous programming is essential for building responsive applications, especially when dealing with time-consuming operations like API calls, file I/O, or database queries. Both C# and JavaScript provide powerful tools to handle asynchronous code: Promises in JavaScript and Tasks in C#. However, managing these manually can lead to complex, nested code. Enter async/awaitāa syntactic sugar that makes asynchronous code look and behave like synchronous code, improving readability and maintainability. Async/Await in JavaScript JavaScript relies heavily on Promises for asynchronous operations. While Promises are powerful, chaining them can lead to callback hell. Async/await simplifies this by allowing us to write asynchronous code in a linear fashion. Scenario: Fetching User Data from an API Instead of chaining .then() calls, we can use async/await to make API calls cleaner. Without Async/Await (Promise Chaining) With Async/Await (Cleaner Approach) Benefits:ā Easier to read ā No nested .then() chains.ā Better error handling ā Structured try/catch blocks. Scenario: Sequential vs. Parallel Execution Sometimes we need to run tasks one after another, while other times we want them to run in parallel for efficiency. Sequential Execution (One After Another) Output: Parallel Execution (Faster Completion) Output: Async/Await in C# C# uses Tasks for asynchronous operations. Before async/await, developers relied on callbacks or .ContinueWith(), leading to complex code. Scenario: Downloading Files Asynchronously Instead of blocking the UI thread, we can use async/await to keep the app responsive. Without Async/Await (Blocking UI) With Async/Await (Non-Blocking UI) Benefits:ā UI remains responsive ā No freezing during downloads.ā Clean error handling ā try/catch works naturally. Scenario: Running Multiple Database Queries If we need to fetch data from multiple sources, async/await makes it easy to manage. Sequential Database Queries Parallel Database Queries (Faster Performance) Key Takeaways ā Use async/await to avoid callback hell in JavaScript and blocking calls in C#.ā Sequential execution (await one by one) vs. parallel execution (Promise.all / Task.WhenAll).ā Error handling is simpler with try/catch instead of .catch() or .ContinueWith().ā Improves performance by keeping UIs responsive while waiting for I/O operations. By adopting async/await, you can write cleaner, more maintainable asynchronous code in both JavaScript and C#. We hope you found this blog useful, and if you would like to discuss anything, you can reach out to us at transform@cloudfonts.com