Your Returns & Refund Processing Data Template
Your Returns & Refund Processing Data Template
- Recommended data fields to collect
- Key process steps to track
- Guidance for data extraction
Returns & Refund Processing Attributes
| Name | Description | ||
|---|---|---|---|
| Event Time EventTime | The timestamp indicating when a specific activity or event occurred. | ||
| Description Event Time, or the timestamp, records the exact date and time that an activity took place. Each activity in the event log has a corresponding timestamp, which provides the chronological order of events. This attribute is critical for all time-based process mining analysis. It is used to calculate cycle times between activities, identify waiting times and bottlenecks, measure overall case duration, and check for compliance with service level agreements (SLAs). The accuracy of the timestamps directly impacts the reliability of any performance analysis. Why it matters This timestamp is essential for calculating all duration-based metrics, such as cycle times and waiting times, which are fundamental to performance analysis. Where to get Corresponds to creation or modification date fields in various tables, such as 'SalesTable.createdDateTime' for order creation or 'WMSJournalTrans.createdDateTime' for warehouse journals. Examples 2023-10-26T10:00:00Z2023-10-26T14:30:15Z2023-10-27T09:05:42Z | |||
| Return Case ID ReturnCaseId | The unique identifier for a customer's return and refund case, linking all related activities. | ||
| Description The Return Case ID serves as the primary identifier for each unique return process instance. It links all activities associated with a specific customer return or refund request, from the initial creation of the return order to its final closure. In process analysis, this ID is fundamental for reconstructing the end-to-end journey of each return. It allows for tracking the complete lifecycle, measuring total cycle times, and analyzing variations between different cases. All events, data, and metrics are aggregated and correlated using this identifier. Why it matters This is the essential case identifier that connects all process steps, making it possible to trace and analyze each return from start to finish. Where to get This is typically the Return Material Authorization (RMA) number or the Sales Order number of type 'Returned Order' in the 'Sales and marketing' module. Found in tables like 'SalesTable' where 'SalesType' is 'Returned Order'. Examples RMA-001234RMA-001235RMA-001236 | |||
| Activity Name ActivityName | The name of the specific business event or task that occurred within the return and refund process. | ||
| Description This attribute describes a specific step or event in the return and refund lifecycle, such as 'Return Order Created', 'Item Received', or 'Credit Note Posted'. Each activity represents a distinct point in the process that is recorded in the system. Analyzing the sequence and frequency of these activities is the core of process mining. It allows for the visualization of process maps, identification of bottlenecks between steps, and discovery of common and uncommon process variants. The set of activities defines the scope of the process being analyzed. Why it matters It defines the steps of the process, allowing for the visualization of the process flow and the identification of bottlenecks, rework, and deviations. Where to get This is a conceptual attribute derived from system events. It can be generated by mapping status changes in tables like 'SalesTable' and 'WMSJournalTable' or specific event logs to user-friendly names. Examples Return Order CreatedItem ReceivedDisposition Code AppliedCredit Note Posted | |||
| Disposition Code DispositionCode | A code indicating the result of the item inspection and the next action to be taken. | ||
| Description The Disposition Code is assigned during the quality inspection of a returned item. It dictates the subsequent step in the process, such as 'Credit', 'Replace', 'Scrap', or 'Return to Customer'. This attribute is a critical decision point in the returns process. Analyzing by disposition code allows businesses to understand the outcomes of returns, track the financial impact of scrapping items, and evaluate the efficiency of different resolution paths, like replacement versus refund. Why it matters This code determines the path a return case will take after inspection, making it crucial for analyzing process variants and their business outcomes. Where to get This is a key field in the quality management module. It is associated with the Quality Order or Inspection Order processing. Examples CRDTREPL-DSCRAPRTV | |||
| Product ID ProductId | The unique identifier for the product being returned. | ||
| Description The Product ID, often the Stock Keeping Unit (SKU), identifies the specific item that is being returned by the customer. Each return order line is associated with a Product ID. Analyzing returns by product is essential for identifying items with high return rates. This can signal quality control problems, inaccurate product descriptions, or manufacturing defects. This analysis helps prioritize product-related investigations and improvements. Why it matters Enables analysis of returns on a per-product basis, helping to identify items with quality issues or high return volumes. Where to get This corresponds to the 'ItemId' field in the 'SalesLine' table for the return order. Examples SKU-A-123SKU-B-456SKU-C-789 | |||
| Responsible User ResponsibleUser | The user or employee who performed or is responsible for a specific activity. | ||
| Description This attribute identifies the individual user responsible for executing a process step. It could be the warehouse worker who received the item, the quality inspector, or the finance clerk who posted the credit note. Analyzing the process by user helps in understanding workload distribution, identifying top performers, and detecting potential training needs. It can also be used to investigate cases handled by specific individuals or teams and ensure proper segregation of duties. Why it matters It allows for analysis of workload distribution, performance by individual or team, and identification of training or resource allocation opportunities. Where to get Found in 'created by' or 'modified by' fields on transaction records, such as 'SalesTable.createdBy' or linked user IDs in journal tables. Examples Alice.WBob.JChris.P | |||
| Return Channel ReturnChannel | The method or channel through which the customer initiated the return. | ||
| Description This attribute specifies the channel used by the customer to start the return process, for example, 'Online Portal', 'In-Store', 'Customer Service Call', or 'Mail'. Segmenting the process analysis by return channel helps in evaluating the performance and efficiency of each channel. A business can compare cycle times, costs, and customer satisfaction across channels to identify best practices and areas for investment or improvement. This is key for the 'Return Channel Utilization Performance' dashboard. Why it matters It allows for performance comparison between different return channels, helping to optimize the most efficient and cost-effective ones. Where to get This information might be stored on the return order header ('SalesTable') or derived from the user who created the order. It may require custom logic or a dedicated field. Examples Web PortalIn-Store KioskCustomer Support | |||
| Return Reason Code ReturnReasonCode | The reason provided by the customer for returning the item. | ||
| Description The Return Reason Code captures the customer's stated reason for the return, such as 'Defective Item', 'Wrong Size', 'Not as Described', or 'No Longer Needed'. This information is typically collected when the return is initiated. Analyzing return reasons is vital for root cause analysis. It helps businesses identify product quality issues, problems with product descriptions, or logistical errors. Insights from this data can drive improvements in product design, marketing, and supply chain operations to reduce future returns. Why it matters Provides critical insight into why returns are happening, enabling root cause analysis to reduce return rates and improve customer satisfaction. Where to get This is typically stored on the return order line level. Look for reason code fields in the 'SalesLine' table for return orders. Examples DEFECTWRONG_ITEMNO_LONGER_WANTEDDAMAGED_IN_TRANSIT | |||
| Actual Refund Amount ActualRefundAmount | The final monetary value of the refund issued to the customer. | ||
| Description This attribute is the final, confirmed amount that was refunded to the customer. This value is recorded when the credit note is created and posted. This is a critical attribute for financial analysis and is directly used in the 'Refund Amount Discrepancy Analysis' dashboard and the 'Refund Amount Accuracy Rate' KPI. Analyzing this data helps to understand the financial impact of returns and any adjustments made during the process. Why it matters This represents the actual financial impact of the return and is crucial for calculating refund accuracy and understanding financial outcomes. Where to get This value can be found in the posted credit note transaction details. It is related to the 'CustTrans' and 'CustInvoiceJour' tables for the credit note. Examples 99.99135.000.00 | |||
| Credit Note ID CreditNoteId | The unique identifier for the credit note document created for a refund. | ||
| Description When a refund is processed, a financial document known as a credit note or credit memo is generated. This attribute stores the unique ID of that document. This ID provides a direct link from the operational return process to the financial records in the accounting system. It is useful for auditing purposes and for deep dives into financial discrepancies, allowing an analyst to trace a return case all the way to the specific financial transaction that settled it. Why it matters It links the operational return process to the corresponding financial transaction, which is crucial for auditing and financial reconciliation. Where to get The credit note number is typically found in the 'InvoiceId' field of the 'CustInvoiceJour' table, where the transaction type is 'Credit note'. This can be linked back to the return order. Examples CN-10056CN-10057CN-10058 | |||
| Customer ID CustomerId | The unique identifier for the customer who initiated the return. | ||
| Description The Customer ID is the unique identifier for the customer account associated with the return. This links the return transaction back to a specific customer in the CRM or customer database. Analyzing returns by customer allows for the identification of customers with unusually high return activity, which might indicate fraudulent behavior or chronic dissatisfaction. It can also be used to segment customers, for example, to offer premium return services to high-value customers. Why it matters It links the return process to a specific customer, enabling customer-level analysis and identification of return patterns or potential fraud. Where to get This is the 'CustAccount' field in the 'SalesTable' for the return order. Examples CUST-00045CUST-00192CUST-00315 | |||
| End Time EndTime | The timestamp indicating when a specific activity was completed. | ||
| Description The End Time represents the completion timestamp for an activity. While StartTime marks the beginning, EndTime marks the conclusion, allowing for the calculation of the processing time for that specific task. This attribute is crucial for detailed performance analysis, especially for tasks with a measurable duration, like 'Item Inspection'. By comparing the StartTime and EndTime, analysts can precisely measure the active processing time of tasks, distinguishing it from the waiting time between tasks. This helps pinpoint inefficiencies within specific activities, not just between them. Why it matters It enables the calculation of active processing time for individual activities, helping to differentiate between waiting time and actual work time. Where to get This often needs to be derived. For example, it could be the 'modifiedDateTime' of a status change that concludes an activity, or it could be the StartTime of the subsequent activity. Examples 2023-10-26T10:15:00Z2023-10-26T14:45:20Z2023-10-27T09:55:12Z | |||
| Is Policy Adherent IsPolicyAdherent | A flag indicating whether the return approval complies with the established return policies. | ||
| Description This is a calculated boolean attribute that indicates if a return meets all the criteria defined in the company's return policy. This could be based on factors like the return window, item condition, or reason for return. This attribute directly supports the 'Return Approval Compliance Overview' dashboard and 'Compliant Return Approval Rate' KPI. It allows the business to quantify policy compliance, identify cases that are approved as exceptions, and analyze the reasons and frequency of such exceptions. This is vital for governance and cost control. Why it matters It directly measures compliance with business rules, helping to identify and reduce non-compliant return approvals that can lead to revenue loss. Where to get This is a derived attribute. The logic would need to be built by comparing attributes of the return (e.g., return date vs. purchase date, return reason) against predefined business rules. Examples truefalse | |||
| Last Data Update LastDataUpdate | The timestamp indicating the last time the data for the process was refreshed. | ||
| Description This attribute records the date and time when the data was last extracted from the source system and updated in the process mining tool. It provides a reference point for the freshness of the data being analyzed. Knowing the last data update time is important for understanding the timeliness of the analysis. It helps users interpret the dashboards and KPIs correctly, knowing if they are looking at real-time data or a snapshot from a specific point in time. This is key for operational monitoring. Why it matters Indicates the freshness of the data, ensuring that analysts are aware of how current their process insights are. Where to get This is a metadata attribute generated and stored during the data ingestion pipeline, typically representing the timestamp of the ETL job completion. Examples 2023-11-01T02:00:00Z2023-11-02T02:00:00Z | |||
| Refund SLA Target Date RefundSlaTargetDate | The target date by which the return and refund case should be fully resolved. | ||
| Description This attribute defines the Service Level Agreement (SLA) deadline for resolving a return case. It is the date by which the customer is expected to have a final resolution, such as a posted refund or a shipped replacement. This target date is essential for performance monitoring against service commitments. It is used to calculate the 'Resolution SLA Adherence Rate' KPI and power the 'Refund Resolution SLA Performance' dashboard. Comparing this date with the actual completion date of the process allows the business to identify SLA breaches and proactively manage aging cases. Why it matters It is the benchmark against which process performance is measured, enabling the tracking of SLA compliance and identification of late cases. Where to get This may not be a standard field. It is often calculated based on the return creation date plus a predefined SLA period (e.g., 14 days). It might be stored in a custom field. Examples 2023-11-10T23:59:59Z2023-11-15T23:59:59Z | |||
| Requested Refund Amount RequestedRefundAmount | The total monetary value of the refund requested by the customer. | ||
| Description This attribute represents the initial refund amount as requested or expected at the beginning of the return process. It is typically based on the original purchase price of the returned items. This value serves as a baseline for the 'Refund Amount Discrepancy Analysis'. By comparing the requested amount to the actual amount refunded, the business can identify discrepancies caused by restocking fees, partial refunds for damaged goods, or other adjustments. This helps in monitoring financial accuracy and policy adherence. Why it matters It serves as a baseline to measure financial accuracy by comparing it against the actual refund amount processed. Where to get This is typically the line amount or total amount from the original sales order line being returned, found in 'SalesLine.LineAmount'. Examples 99.99150.0024.50 | |||
| Return Order Status ReturnOrderStatus | The overall status of the return order at the time of the event. | ||
| Description This attribute indicates the current status of the return order header, such as 'Open', 'Invoiced', or 'Canceled'. It provides a high-level view of where the case is in its lifecycle. While activities provide granular process steps, the overall status is useful for filtering and segmenting cases. For example, an analyst might want to focus only on 'Open' cases to understand current workload, or analyze the process flow of cases that ultimately get 'Canceled'. Why it matters Provides a high-level summary of the case's state, which is useful for filtering cases and understanding outcomes like cancellations. Where to get This information is located in the 'SalesStatus' or 'DocumentStatus' field of the 'SalesTable'. Examples Open orderDeliveredInvoicedCanceled | |||
| Return Type ReturnType | Categorizes the return based on the expected outcome, such as Refund or Replacement. | ||
| Description This attribute classifies the return case based on the resolution type sought by the customer or offered by the business. Common types include a monetary 'Refund', an exchange for a 'Replacement' item, or 'Repair'. This categorization is useful for analyzing different process paths. The process for issuing a refund is significantly different from the process for shipping a replacement item. Segmenting by Return Type allows for a more accurate analysis of the cycle times and bottlenecks specific to each resolution path. Why it matters It allows for the segmentation of analysis based on the intended outcome, as refund and replacement processes have different steps and cycle times. Where to get This may be a custom field on the return order header or derived based on the disposition code or subsequent transactions like the creation of a replacement sales order. Examples RefundReplacementStore Credit | |||
| SLA Status SlaStatus | Indicates whether the case was resolved within the Service Level Agreement target. | ||
| Description This calculated attribute provides a simple status of SLA compliance, typically 'On Time' or 'Late'. It is determined by comparing the timestamp of the final activity (e.g., 'Return Order Closed') with the 'RefundSlaTargetDate'. This attribute simplifies performance reporting on dashboards like 'Refund Resolution SLA Performance'. Instead of requiring users to compare dates, it provides a direct and easily understandable status. This allows for quick filtering and aggregation to calculate the overall 'Resolution SLA Adherence Rate'. Why it matters Provides a simple, at-a-glance indicator of SLA compliance, making it easy to filter for late cases and analyze the root causes of delays. Where to get This is a derived attribute, calculated by comparing the timestamp of the final resolution activity against the 'RefundSlaTargetDate' attribute. Examples On TimeLate | |||
| Source System SourceSystem | The information system from which the event data was extracted. | ||
| Description This attribute identifies the source information system where the data originated. In this context, it will primarily be 'Microsoft Dynamics 365'. In larger organizations, a process might span multiple systems. Specifying the source system for each event is crucial for data governance, troubleshooting data extraction issues, and understanding the technological landscape of the process. It confirms the origin of the data being analyzed. Why it matters It provides crucial context about data origin, which is essential for data governance, validation, and understanding the system landscape of the process. Where to get This is typically a static value added during the data extraction, transformation, and loading (ETL) process to label the dataset's origin. Examples Microsoft Dynamics 365 F&OD365-PROD | |||
| Warehouse ID WarehouseId | The identifier for the warehouse or location where the returned item is received. | ||
| Description This attribute identifies the specific physical warehouse or return center that processes the returned item. Different locations may have different processes, resources, or performance levels. Analyzing the process by warehouse allows for performance benchmarking between locations. It can help identify which facilities are most efficient at processing returns, highlight regional bottlenecks, and inform decisions about resource allocation and process standardization across the logistics network. Why it matters Enables performance comparison between different warehouses or return centers, helping to identify regional bottlenecks or best practices. Where to get This information is stored in the 'InventLocationId' field on inventory-related transactions, such as the Arrival Journal ('WMSJournalTable') or on the 'SalesLine'. Examples WH-EASTWH-WESTCENTRAL-DC | |||
Returns & Refund Processing Activities
| Activity | Description | ||
|---|---|---|---|
| Credit Note Posted | The credit note is officially posted to the financial ledgers, making the credit available to the customer. This signifies the completion of the refund action from the company's perspective. | ||
| Why it matters This is a crucial financial milestone, confirming the refund has been processed in the system. It is often a key activity for measuring refund SLA compliance. Where to get The posting timestamp of the invoice journal for the return order, which finalizes the credit note. The status of the return order changes to 'Invoiced'. Capture Posting of the return order's invoice journal. Event type explicit | |||
| Disposition Code Applied | This activity represents the completion of the inspection and the decision on what to do with the returned item. A disposition code, such as 'Credit', 'Scrap', or 'Replace', is assigned to the return line. | ||
| Why it matters This is a key decision-making point that determines the subsequent process path, whether a refund, exchange, or rejection. Delays here can significantly impact overall resolution time. Where to get This event is captured when the DispositionCode field is populated on the return order line's inventory transaction or related journal. Capture The update event when a DispositionCode is set for the return order line. Event type explicit | |||
| Item Received | Marks the physical receipt of the returned item at the warehouse or designated return center. This is captured when the arrival journal associated with the return order is posted. | ||
| Why it matters This is a critical milestone that transitions the process from customer action to internal processing. It is the starting point for calculating all internal handling times, such as inspection and disposition. Where to get The posting timestamp of the WMS Journal or Item Arrival Journal associated with the ReturnOrder line. This updates inventory transactions to a 'Registered' or 'Received' status. Capture Posting event of the Item Arrival Journal linked to the return order line. Event type explicit | |||
| Return Order Closed | The return order has reached its final state, meaning all physical and financial transactions are complete. This typically occurs after the credit note is posted or the replacement is shipped. | ||
| Why it matters This is the primary end event for a successfully completed return process. The duration from creation to this point represents the total case cycle time. Where to get Inferred from the ReturnOrder status field changing to its terminal value, such as 'Invoiced' or 'Closed'. This indicates no further processing is expected. Capture Change of the SalesTable.Status or SalesTable.DocumentStatus field to a final state. Event type inferred | |||
| Return Order Created | This activity marks the initiation of the return process, where a Return Material Authorization (RMA) or Return Order is created in the system. This is an explicit event captured upon the creation of a new ReturnOrder record in Dynamics 365. | ||
| Why it matters This is the primary start event for the entire returns process. Analyzing the time from this activity to others reveals overall process lead time and helps identify early-stage bottlenecks. Where to get This event is captured from the creation timestamp of the ReturnOrder header. This is typically found in the SalesTable where the SalesType is 'Returned Order'. Capture Creation event of the SalesTable record with SalesType = 'Returned Order'. Event type explicit | |||
| Arrival Journal Created | This activity signifies that the warehouse is expecting the returned item to arrive. It's the creation of an arrival journal, which prepares the system for the physical receipt of the goods. | ||
| Why it matters This step separates logistical preparation from the actual physical receipt. It helps in analyzing warehouse readiness and planning for incoming returns. Where to get Creation of a record in the WMSJournalTable with JournalType 'Arrival'. The journal is linked to the return order line. Capture Creation timestamp of the WMSJournalTable record for the return. Event type explicit | |||
| Credit Note Created | A credit note is generated based on a disposition of 'Credit', authorizing a refund to the customer. This is the formal start of the financial settlement part of the process. | ||
| Why it matters This activity marks the approval of the financial refund. The time between disposition and credit note creation highlights administrative delays in initiating the refund. Where to get This can be inferred from the creation of a new SalesTable record with a negative value, linked to the original return order, or by running the 'Create credit note' batch job. Capture Creation of a credit note, often by posting the return order invoice. Event type explicit | |||
| Quality Order Generated | A formal quality order is created, indicating the returned item must undergo a structured inspection process. This is common in scenarios where returns require detailed testing or checks against quality standards. | ||
| Why it matters This activity signifies the start of a formal inspection process. Tracking time from this point helps measure the efficiency and duration of the quality assurance workflow. Where to get Creation timestamp of a record in the InventQualityOrderTable linked to the return order. Capture Creation of an InventQualityOrderTable record. Event type explicit | |||
| Replacement Item Shipped | The replacement item's packing slip is posted, indicating it has been shipped to the customer. This marks the completion of the exchange fulfillment process. | ||
| Why it matters This is a key milestone in the exchange variant, representing the fulfillment of the company's obligation to the customer. It's crucial for tracking exchange cycle times. Where to get The posting date of the packing slip journal for the replacement sales order. This updates the order status to 'Delivered'. Capture Posting of the packing slip for the replacement sales order. Event type explicit | |||
| Replacement Order Created | A new sales order is created to send a replacement item to the customer. This activity occurs when the disposition action is 'Replace and Credit' or 'Replace and Scrap'. | ||
| Why it matters This activity initiates the exchange process variant. Tracking this path separately from the refund path is essential for understanding the complexities and costs of exchanges. Where to get The creation of a new SalesTable record for the replacement item, often automatically generated and linked to the original return order. Capture Creation of a new Sales Order linked to the Return Order via the disposition action. Event type explicit | |||
| Return Order Cancelled | The return order is cancelled before completion. This could be due to a customer request or if the item was never returned. | ||
| Why it matters This represents an alternative, unsuccessful end to the process. Analyzing why returns are cancelled can provide insights into customer behavior or process failures. Where to get Inferred from the ReturnOrder status field changing to 'Cancelled'. This is a distinct terminal state from a successfully closed order. Capture Change of the SalesTable.Status field to 'Cancelled'. Event type inferred | |||
| Return Order Confirmed | Represents the formal confirmation of the return order within the system, often triggering downstream logic. This is typically captured as an explicit action or a status change on the ReturnOrder header. | ||
| Why it matters Confirmation is a key step before logistics can begin. Delays between creation and confirmation can indicate administrative or system-related backlogs. Where to get This can be identified by the 'Confirmation' journal posting for the return order or a change in the DocumentStatus field on the SalesTable. Capture Execution of the 'Confirm sales order' function for the return order. Event type explicit | |||
Extraction Guides
Steps
- Prerequisite: Register an Application in Azure Active Directory. Before you can connect to the Dynamics 365 API, you must register an application in your Azure AD tenant. Grant this application delegated permissions to access Dynamics 365 Finance & Operations, for example, the
Financials.ReadWrite.Allor a custom permission. - Configure Application ID in Dynamics 365. In Dynamics 365, navigate to System administration > Setup > Azure Active Directory applications. Add the Application (client) ID from your Azure AD app registration and associate it with a user account that has the necessary security roles to read the required data entities.
- Obtain an OAuth 2.0 Access Token. Write a script, for instance in PowerShell or Python, to authenticate against the Microsoft identity platform endpoint. Use the application's credentials (client ID and secret) to request an access token for the Dynamics 365 resource URL.
- Identify Your Dynamics 365 Environment URL. Locate the base URL for your Dynamics 365 environment. The Web API endpoint will typically look like this:
https://[YourD365FinanceAndOpsURL].dynamics.com/data. - Construct and Execute OData API Requests. For each of the 12 required activities, construct a specific OData GET request URL. Use
$selectto retrieve only the required columns and$filterto specify the date range and any status conditions. The authentication token obtained in step 3 must be included as a Bearer token in the authorization header of each request. - Develop an Extraction Script. Create a script that iterates through the list of OData requests. This script should handle the authentication, execute each GET request, and store the resulting JSON data. Pay attention to API limits and implement pauses if necessary.
- Handle API Pagination. Dynamics 365 paginates large results. Your script must check for an
@odata.nextLinkproperty in the response. If it exists, your script needs to make a subsequent request to that URL to retrieve the next page of data, continuing until nonextLinkis provided. - Transform and Union the Data. Process the JSON response from each of the 12 API calls. For each activity, create a standardized record containing
ReturnCaseId,ActivityName,EventTime, and other attributes. For example, for the 'Return Order Created' event, map theReturnOrderNumbertoReturnCaseId, setActivityNameto 'Return Order Created', and mapcreatedDateTimetoEventTime. Combine the transformed records from all calls into a single list or table. - Clean and Standardize Timestamps. Ensure all
EventTimevalues are in a consistent format, preferably UTC with a format likeYYYY-MM-DDTHH:MM:SSZ. Handle any records with missing or invalid timestamps as needed. - Export the Final Event Log. Once all data is collected and transformed into a single unified dataset, export it to a CSV file. Ensure the column headers match the requirements for ProcessMind:
ReturnCaseId,ActivityName,EventTime,ResponsibleUser,DispositionCode, etc. The file is now ready for upload.
Configuration
- API Endpoint URL: The base URL for your Dynamics 365 Finance & Operations instance. It follows the format
https://[YourEnvironmentName].dynamics.com/data. - Azure AD Application: An application must be registered in Azure AD with a client ID and secret. It requires API permissions to access Dynamics 365 data entities.
- Date Range Filtering: It is critical to apply a date range filter in every API call using the OData
$filterparameter on a relevant date field, such ascreatedDateTimeormodifiedDateTime. A typical starting range is the last 3 to 6 months of data to keep the extraction manageable. - Company Filter: To extract data for a specific legal entity, include the
cross-company=truequery parameter and then use$filteron thedataAreaIdfield. For example,?cross-company=true&$filter=dataAreaId eq '[YourCompanyCode]'. - Pagination Preference: Use the
Prefer: odata.maxpagesize=[value]header in your requests to control the number of records returned per page. A value of1000to5000is common. This helps prevent API timeouts on large entities. - API Throttling: Be aware of Dynamics 365 API service protection limits. The extraction script should include logic to handle
429 (Too Many Requests)responses, typically by implementing an exponential backoff or a simple pause-and-retry mechanism.
a Sample Query graphql
/*
This is a conceptual guide representing multiple, distinct OData API calls.
You will need a script (e.g., Python, PowerShell) to execute these calls sequentially,
authenticate with a bearer token, handle pagination, and union the results into a single file.
Replace [YourD365URL], [StartDate], [EndDate], and [YourCompanyCode] with your specific values.
*/
// Base URL for all requests
const string BaseUrl = "https://[YourD365URL].dynamics.com/data";
const string CompanyFilter = "?cross-company=true&$filter=dataAreaId eq '[YourCompanyCode]' and ";
const string DateFilterCreated = "createdDateTime ge [StartDate]T00:00:00Z and createdDateTime le [EndDate]T23:59:59Z";
const string DateFilterModified = "modifiedDateTime ge [StartDate]T00:00:00Z and modifiedDateTime le [EndDate]T23:59:59Z";
// 1. Return Order Created
GET {BaseUrl}/ReturnOrderHeaders{CompanyFilter}{DateFilterCreated}&$select=ReturnOrderNumber,createdDateTime,createdby,ReturnReasonCodeId
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Return Order Created' -> ActivityName, createdDateTime -> EventTime, createdby -> ResponsibleUser, ReturnReasonCodeId -> ReturnReasonCode
// 2. Return Order Confirmed
// This often updates the header status. We look for a modification time on confirmed orders.
GET {BaseUrl}/ReturnOrderHeaders{CompanyFilter}ReturnOrderStatus eq 'Confirmed' and {DateFilterModified}&$select=ReturnOrderNumber,modifiedDateTime,modifiedby,ReturnReasonCodeId
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Return Order Confirmed' -> ActivityName, modifiedDateTime -> EventTime, modifiedby -> ResponsibleUser
// 3. Arrival Journal Created
GET {BaseUrl}/WarehouseArrivalJournalHeaders{CompanyFilter}{DateFilterCreated}&$expand=WarehouseArrivalJournalLines($select=InventTransactionId)&$select=JournalNumber,createdDateTime,createdby
// Note: This requires post-processing to link JournalNumber to a ReturnCaseId via InventTransactionId.
// Mapping: Link via InventTrans -> ReturnCaseId, 'Arrival Journal Created' -> ActivityName, createdDateTime -> EventTime, createdby -> ResponsibleUser
// 4. Item Received (Arrival Journal Posted)
GET {BaseUrl}/WarehouseArrivalJournalHeaders{CompanyFilter}JournalPosted eq 'Yes' and {DateFilterModified}&$expand=WarehouseArrivalJournalLines($select=InventTransactionId)&$select=JournalNumber,modifiedDateTime,modifiedby
// Mapping: Link via InventTrans -> ReturnCaseId, 'Item Received' -> ActivityName, modifiedDateTime -> EventTime, modifiedby -> ResponsibleUser
// 5. Quality Order Generated
GET {BaseUrl}/InventQualityOrders{CompanyFilter}{DateFilterCreated}&$select=QualityOrderId,InventTransId,createdDateTime,CreatedByUserId,ItemId
// Mapping: Link via InventTransId -> ReturnCaseId, 'Quality Order Generated' -> ActivityName, createdDateTime -> EventTime, CreatedByUserId -> ResponsibleUser, ItemId -> ProductId
// 6. Disposition Code Applied
// This is a status change on the return line.
GET {BaseUrl}/ReturnOrderLines{CompanyFilter}ReturnDispositionCodeId ne '' and {DateFilterModified}&$select=ReturnOrderNumber,modifiedDateTime,modifiedby,ReturnDispositionCodeId,ItemId
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Disposition Code Applied' -> ActivityName, modifiedDateTime -> EventTime, modifiedby -> ResponsibleUser, ReturnDispositionCodeId -> DispositionCode, ItemId -> ProductId
// 7. Credit Note Created
// Look for sales orders with type 'Returned Order' that are not yet invoiced.
GET {BaseUrl}/SalesOrderHeadersV2{CompanyFilter}SalesOrderProcessingStatus eq 'Open' and SalesOrderType eq 'ReturnedOrder' and {DateFilterCreated}&$select=SalesOrderNumber,createdDateTime,createdby
// Mapping: SalesOrderNumber -> ReturnCaseId, 'Credit Note Created' -> ActivityName, createdDateTime -> EventTime, createdby -> ResponsibleUser
// 8. Credit Note Posted
// Look for posted invoice journals linked to a return order.
GET {BaseUrl}/SalesInvoiceJournalHeaders{CompanyFilter}SalesOrderType eq 'ReturnedOrder' and {DateFilterCreated}&$select=SalesOrderNumber,InvoiceDate,createdby
// Mapping: SalesOrderNumber -> ReturnCaseId, 'Credit Note Posted' -> ActivityName, InvoiceDate -> EventTime, createdby -> ResponsibleUser
// 9. Replacement Order Created
// Disposition code on the return line triggers a replacement order.
GET {BaseUrl}/SalesOrderHeadersV2{CompanyFilter}SalesOrderOriginType eq 'ReturnOrder' and {DateFilterCreated}&$select=SalesOrderNumber,createdDateTime,createdby,ReturnOrderNumber
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Replacement Order Created' -> ActivityName, createdDateTime -> EventTime, createdby -> ResponsibleUser
// 10. Replacement Item Shipped
// Check for posted packing slips related to the replacement sales order.
GET {BaseUrl}/SalesPackingSlipJournals{CompanyFilter}{DateFilterCreated}&$select=SalesOrderNumber,DeliveryDate,createdby
// Note: This requires linking SalesOrderNumber back to the original ReturnOrderNumber for the ReturnCaseId.
// Mapping: Link SalesOrderNumber -> ReturnCaseId, 'Replacement Item Shipped' -> ActivityName, DeliveryDate -> EventTime, createdby -> ResponsibleUser
// 11. Return Order Closed
GET {BaseUrl}/ReturnOrderHeaders{CompanyFilter}ReturnOrderStatus eq 'Closed' and {DateFilterModified}&$select=ReturnOrderNumber,modifiedDateTime,modifiedby
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Return Order Closed' -> ActivityName, modifiedDateTime -> EventTime, modifiedby -> ResponsibleUser
// 12. Return Order Cancelled
GET {BaseUrl}/ReturnOrderHeaders{CompanyFilter}ReturnOrderStatus eq 'Canceled' and {DateFilterModified}&$select=ReturnOrderNumber,modifiedDateTime,modifiedby
// Mapping: ReturnOrderNumber -> ReturnCaseId, 'Return Order Cancelled' -> ActivityName, modifiedDateTime -> EventTime, modifiedby -> ResponsibleUser Steps
- Enable TDS Endpoint: Ensure the Tabular Data Stream (TDS) endpoint is enabled for your Dynamics 365 Dataverse environment. A system administrator can enable this in the Power Platform admin center under Environment > Settings > Features.
- Identify Environment URL: Find your environment URL. It typically looks like
yourorg.crm.dynamics.com. The TDS endpoint server name will be this URL with port 5558, for example,yourorg.crm.dynamics.com,5558. - Connect with a SQL Client: Use a SQL client that supports TDS, such as SQL Server Management Studio (SSMS) or Azure Data Studio.
- Authenticate: Connect to the server using your Azure Active Directory account that has appropriate permissions, typically System Administrator or System Customizer, in the Dataverse environment.
- Prepare the Query: Copy the complete SQL query provided in the
querysection of this document into a new query window in your SQL client. - Set Parameters: Locate the placeholders within the query. Replace
'{StartDate}'and'{EndDate}'with the desired date range for the extraction, for example,'2023-01-01'and'2023-12-31'. Also, update any placeholder values for status codes or disposition codes to match your specific Dynamics 365 configuration. - Execute the Query: Run the modified query against the Dataverse database. The execution time will vary depending on the data volume and the selected date range.
- Review Results: Once the query completes, review the returned dataset to ensure it contains the expected columns:
ReturnCaseId,ActivityName,EventTime, and the recommended attributes. - Export the Event Log: Export the query results to a CSV file. Most SQL clients have a built-in function to save results directly to a file. Ensure the file is saved with UTF-8 encoding.
- Upload to ProcessMind: The exported CSV file is now ready to be uploaded to ProcessMind as a new event log for process mining analysis.
Configuration
- Prerequisites: You must have a user account with at least read access to the relevant Dataverse tables (e.g., SalesTable, SalesLine, CustInvoiceJour). Permissions are typically managed through security roles like System Administrator or a custom role with sufficient table permissions.
- TDS Endpoint: The Dataverse TDS endpoint must be enabled for the environment. This feature allows for direct, read-only SQL queries against the Dataverse database.
- Date Range: The query includes
'{StartDate}'and'{EndDate}'placeholders. For initial analysis, a date range of 3 to 6 months is recommended to provide a representative dataset without causing performance issues. - Company Filter: The query as written will run across all legal entities (companies) the user has access to. For a single company analysis, uncomment and add a
WHEREclause filtering on theDATAAREAIDfield in each part of theUNION ALLstatement, for example,AND st.DATAAREAID = '[YourCompanyID]'. - Custom Logic Placeholders: The query contains placeholders like
[YourReplaceCode1]for disposition codes and notes on linking replacement orders. These must be configured based on your specific business process and Dynamics 365 setup. - Performance: Direct queries against the TDS endpoint for large datasets can be slow. The connection is optimized for analytical queries, but complex joins across millions of rows may time out. It is recommended to apply strict date filters.
a Sample Query sql
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Return Order Created' AS ActivityName,
st.CREATEDDATETIME AS EventTime,
st.CREATEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Return Order Confirmed' AS ActivityName,
st.MODIFIEDDATETIME AS EventTime,
st.MODIFIEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.DOCUMENTSTATUS = 1 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Arrival Journal Created' AS ActivityName,
wjt.CREATEDDATETIME AS EventTime,
wjt.CREATEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
JOIN WMSJOURNALTABLE wjt ON st.SALESID = wjt.ORDERID AND st.DATAAREAID = wjt.DATAAREAID
WHERE st.SALESTYPE = 3 AND wjt.JOURNALTYPE = 4 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Item Received' AS ActivityName,
wjt.POSTEDDATETIME AS EventTime,
wjt.POSTEDUSERID AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
JOIN WMSJOURNALTABLE wjt ON st.SALESID = wjt.ORDERID AND st.DATAAREAID = wjt.DATAAREAID
WHERE st.SALESTYPE = 3 AND wjt.JOURNALTYPE = 4 AND wjt.POSTEDDATETIME IS NOT NULL AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Quality Order Generated' AS ActivityName,
iqot.CREATEDDATETIME AS EventTime,
iqot.CREATEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
iqot.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
JOIN INVENTQUALITYORDERTABLE iqot ON sl.INVENTTRANSID = iqot.INVENTTRANSID AND sl.DATAAREAID = iqot.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Disposition Code Applied' AS ActivityName,
iqot.VALIDATEDDATETIME AS EventTime,
iqot.VALIDATEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
iqot.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
JOIN INVENTQUALITYORDERTABLE iqot ON sl.INVENTTRANSID = iqot.INVENTTRANSID AND sl.DATAAREAID = iqot.DATAAREAID
WHERE st.SALESTYPE = 3 AND iqot.VALIDATEDDATETIME IS NOT NULL AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Credit Note Created' AS ActivityName,
st.MODIFIEDDATETIME AS EventTime,
st.MODIFIEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.SALESSTATUS = 3 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Credit Note Posted' AS ActivityName,
cij.CREATEDDATETIME AS EventTime,
cij.CREATEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
JOIN CUSTINVOICEJOUR cij ON st.SALESID = cij.SALESID AND st.DATAAREAID = cij.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
ro.RETURNITEMNUM AS ReturnCaseId,
'Replacement Order Created' AS ActivityName,
replacement_so.CREATEDDATETIME AS EventTime,
replacement_so.CREATEDBY AS ResponsibleUser,
NULL AS DispositionCode,
NULL AS ReturnReasonCode,
replacement_so.SALESORIGINID AS ReturnChannel,
replacement_sl.ITEMID AS ProductId
FROM SALESTABLE ro
JOIN SALESLINE rol ON ro.SALESID = rol.SALESID AND ro.DATAAREAID = rol.DATAAREAID
JOIN SALESTABLE replacement_so ON ro.CUSTACCOUNT = replacement_so.CUSTACCOUNT AND ro.DATAAREAID = replacement_so.DATAAREAID
JOIN SALESLINE replacement_sl ON replacement_so.SALESID = replacement_sl.SALESID AND replacement_so.DATAAREAID = replacement_sl.DATAAREAID
WHERE ro.SALESTYPE = 3
AND rol.RETURNDISPOSITIONCODEID IN ('[YourReplaceCode1]', '[YourReplaceCode2]')
AND replacement_so.SALESTYPE = 1
AND replacement_so.CREATEDDATETIME > ro.CREATEDDATETIME
-- The join above is a basic example and must be replaced with your system's specific logic for linking returns to replacements.
AND ro.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
ro.RETURNITEMNUM AS ReturnCaseId,
'Replacement Item Shipped' AS ActivityName,
cpsj.CREATEDDATETIME AS EventTime,
cpsj.CREATEDBY AS ResponsibleUser,
NULL AS DispositionCode,
NULL AS ReturnReasonCode,
replacement_so.SALESORIGINID AS ReturnChannel,
cpsl.ITEMID AS ProductId
FROM SALESTABLE ro
JOIN SALESLINE rol ON ro.SALESID = rol.SALESID AND ro.DATAAREAID = rol.DATAAREAID
JOIN SALESTABLE replacement_so ON ro.CUSTACCOUNT = replacement_so.CUSTACCOUNT AND ro.DATAAREAID = replacement_so.DATAAREAID
JOIN CUSTPACKINGSLIPJOUR cpsj ON replacement_so.SALESID = cpsj.SALESID AND replacement_so.DATAAREAID = cpsj.DATAAREAID
JOIN CUSTPACKINGSLIPTRANS cpsl ON cpsj.PACKINGSLIPID = cpsl.PACKINGSLIPID AND cpsj.SALESID = cpsl.SALESID AND cpsj.DATAAREAID = cpsl.DATAAREAID
WHERE ro.SALESTYPE = 3
AND rol.RETURNDISPOSITIONCODEID IN ('[YourReplaceCode1]', '[YourReplaceCode2]')
AND replacement_so.SALESTYPE = 1
AND replacement_so.CREATEDDATETIME > ro.CREATEDDATETIME
-- The join above is a basic example and must be replaced with your system's specific logic for linking returns to replacements.
AND ro.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Return Order Closed' AS ActivityName,
st.MODIFIEDDATETIME AS EventTime,
st.MODIFIEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.SALESSTATUS = 3 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
SELECT
st.RETURNITEMNUM AS ReturnCaseId,
'Return Order Cancelled' AS ActivityName,
st.MODIFIEDDATETIME AS EventTime,
st.MODIFIEDBY AS ResponsibleUser,
sl.RETURNDISPOSITIONCODEID AS DispositionCode,
sl.RETURNREASONCODEID AS ReturnReasonCode,
st.SALESORIGINID AS ReturnChannel,
sl.ITEMID AS ProductId
FROM SALESTABLE st
JOIN SALESLINE sl ON st.SALESID = sl.SALESID AND st.DATAAREAID = sl.DATAAREAID
WHERE st.SALESTYPE = 3 AND st.SALESSTATUS = 4 AND st.CREATEDDATETIME BETWEEN '{StartDate}' AND '{EndDate}';