top of page
Writer's pictureAlan Campbell

Crafting a Python Function App for Trend Analysis – Part 1

Updated: Oct 30, 2023

In our opening blog, we explored Sales Trend Analysis, highlighting its role in improving business decisions. Through this lens, we saw how analyzing sales trends sheds light on past performances and guides future strategies with data-driven assurance. This led us to Microsoft Dynamics 365 Business Central, where the Power Automate workflow is primed to harness the capabilities of a Python Function App in Azure, promising a consistent flow of actionable insights for informed decision-making.


As we step into this second blog, we focus on the pivotal Python Function App. We'll navigate through the crafting of a Python script set to morph into an Azure Function App. This app will translate raw sales data into intuitive charts reflecting the sales trends of particular Business Central item numbers, turning data into a visual narrative.


We'll cover the script's birth, dive into its core logic, and observe its transformation into an Azure Function App. Along this coding voyage, we'll reveal the steps to leverage the Python Function App to unearth insights from sales data, showcasing how this app is key in our broader narrative of automating sales trend analysis and response orchestration.


On this leg, we aim to equip you with the essential knowledge and code snippets for your Python Function App journey. This endeavor unveils how Python and Azure synergize to elevate sales data understanding, translating it into actionable intelligence.


As we near the practical aspect of sales trend analysis, the theme of turning data into a trusted ally for decision-making remains our guiding narrative. Stay with us on this enlightening journey as we code through uncertainties towards a horizon of insightful decisions, each code line drawing us nearer to a data-informed business outlook.


Your stride into actionable intelligence is accelerating, and this Python Function App marks your next leap towards fostering a data-centric culture in your business. Join us as we continue coding our way to insightful decision-making.


The Python Script


The Python script we are set to develop is straightforward yet impactful. It's designed to receive a list of Business Central x and y data from the Power Platform custom connector, which we will introduce in our next blog. Here, x and y denote the months and corresponding sales figures, respectively, extracted from the Item Ledger history.


Upon receiving the data, the script's primary task is to generate a chart. This chart will exhibit the item's monthly sales data, providing a clear visual representation of sales performance over time. In addition to plotting the sales data, the script will calculate and overlay a trend line onto the chart. This trend line is crucial as it helps in visualizing the general sales trend and projecting future performance at a glance.

this image shows the trend line for business central item number 1928-S that was created by a Power Automate Workflow calling a Python Function App in Azure
Business Central Item Number 1928-S Sales Trend

The final output will be a chart image which not only encapsulates the historical sales data but also includes a trend line that provides a directional insight into the sales trend. This image is then ready to be sent back through the Power Platform custom connector, rendering a visual narrative of the sales data which can be easily interpreted by decision-makers.


Below is the Python script that we will employ as the solution backbone for this blog series:


import os
import json
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import tempfile
import azure.functions as func
import base64

def main(req: func.HttpRequest) -> func.HttpResponse:
    try:
        # Get JSON data from the HTTP request
        req_body = req.get_json()
        
        # Parse the x and y data
        x = list(map(int, req_body["x"].split(',')))
        y = list(map(int, req_body["y"].split(',')))
        
        # Perform linear regression
        slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
        
        # Create a line using the regression parameters
        regression_line = [slope*xi + intercept for xi in x]
        
        # Plot the data along with the regression line
        plt.scatter(x, y, color='blue')  # Scatter plot of the data points
        plt.plot(x, regression_line, color='red')  # The regression line
        plt.xlabel('Months')
        plt.ylabel('Sales')
        plt.title('Item Sales by Month')
        plt.grid(True)

        # Save the plot to a temporary file
        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp:
            plt.savefig(temp.name, format="png")
        
        # Read the image file and encode it to base64
        with open(temp.name, "rb") as f:
            encoded_image = base64.b64encode(f.read()).decode('utf-8')
        
        # Build the JSON response
        response = {
            "slope": slope,
            "intercept": intercept,
            "r_value": r_value,
            "p_value": p_value,
            "std_err": std_err,
            "image": encoded_image
        }
        
        # Delete the temporary file
        os.remove(temp.name)

        # Return the JSON response
        return func.HttpResponse(json.dumps(response), mimetype="application/json")
        
    except ValueError as e:
        return func.HttpResponse(str(e), status_code=400)
    except Exception as e:
        return func.HttpResponse(str(e), status_code=500)

To set up the development environment, configure Azure, deploy the script into an Azure Function App, and test the app, please refer to my previous blog on this topic.


Testing Your Function App Using Postman


Testing the function app will follow the same procedure as outlined in the reference blog, with a notable difference in the output. Unlike the scenario depicted in the reference blog, the output here will include an image.


a. Add a new request in Postman.

b. Select POST and paste in the URL that you copied in the Azure.

c. In the Body section click on raw.

d. Paste the following JSON in the Body and click on Send


{
  "x": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14",
  "y": "4535,3887,6477,4534,6477,3239,5182,5182,2592,3888,1944,3239,5829,3886,4000"
}

e. Your response should look like this:


{
    "slope": -96.64999999999999,
    "intercept": 5002.616666666667,
    "r_value": -0.3247983548185419,
    "p_value": 0.2375335363376549,
    "std_err": 78.05630651766381,
    "image": "iVBORw0KGgoAAAANSUhEUgAAAoOXRFWHRTb2......
}

Conclusion


As we wrap up this segment of our blog series, we've embarked on a crucial step towards harnessing the power of sales trend analysis. Through the lens of a Python Function App, we've bridged the gap between raw sales data and actionable visual insights. Our script, simple in design yet robust in execution, serves as a testament to the potential of blending Python with Azure to interpret sales data.

In this chapter, we navigated through the creation of a Python script, unveiling its capability to transmute sales figures into a coherent visual narrative. This visual representation, enriched with a trend line, not only reflects past sales performances but also provides a glimpse into potential future trends. It's a step towards making data more accessible and comprehensible for decision-makers, thereby fostering a data-driven culture within the business realm.

As we have now laid out the script that will act as the backbone of our solution, the stage is set for our next adventure where we will delve into the Power Platform custom connector. This connector will serve as the conduit, channeling data between Microsoft Dynamics 365 Business Central and our Python Function App, enabling a seamless flow of information.

We're on a path towards constructing a solution that will not only notify decision-makers of significant deviations in sales trends but also provide them with a visual context to better understand these trends. Our journey continues to be as exciting as it is enlightening, and as we progress, we inch closer to a holistic solution aimed at amplifying the decision-making narrative with data-centric insights.

Thank you for accompanying us on this leg of our journey, and we eagerly look forward to unraveling more layers of this solution together in the forthcoming blogs.

40 views0 comments

Comments


bottom of page