Management, finance and ESGBI, AI and ML for the business
B2B customers at risk of churning
A customer who is leaving does not announce it: they order less often and spend less. Every Monday Muvia scores each customer's risk with a Python function on their orders and sends every sales rep the list of who to call first, ranked by value.
Illustrative scenario: it describes a typical case, not a customer project.
By the time the drop reaches revenue, the customer has gone.
In B2B a customer rarely ends the relationship with a phone call. They order every six weeks instead of every three, buy fewer lines, move part of their purchases elsewhere. Monthly totals hide it, and the sales rep notices when it is too late.
The signal is already in the orders: it has to be worked out for each customer, compared with that customer's own history and put in front of the person who can pick up the phone, every week.
- Who it's for
- Sales leadership, area managers and sales reps; customer service and management accounting for the value at risk.
In Muvia, step by step
Real product screens, recorded on a project with sample data.
The video · A customer who is leaving does not announce it: they order less often and spend less. Every Monday Muvia scores each customer's risk with a Python function on their orders and sends every sales rep the list of who to call first, ranked by value.
What you get
- The drop shows in the orders
- Risk rises as the customer slows down, weeks before the quarter's revenue shows it.
- Every rep knows who to call
- The list arrives on Monday morning, already ranked by value, without asking for an extract.
- Risk has a value
- Next to the score sits the customer's revenue: management sees what is at stake and where it is concentrated.
- The rule belongs to the team
- The score is code the team can read and change; a new rule is a new version of the function, not another spreadsheet.
For the technical team
How it is built in Muvia
- 1
Connect orders and the CRM
Orders arrive with an incremental copy of the ERP database every night, customers and reps through the Salesforce connector. A query joins them on the customer code.
- 2
Write the risk in Python
A Python function compares each customer's order frequency and spend over the last three months with their past year and turns it into a score. A trial run on a sample writes nothing; Athena can draft the code.
- 3
Schedule it every Monday
A flow runs the function every Monday at 7 am and writes the scores to a managed table, which dashboards, notebooks and alarms read like any other data.
- 4
Show risk by sales rep
A dashboard plots each customer's risk against their value and adds up the revenue at risk per rep: you see at once where it is concentrated.
- 5
Send the list to the rep
A notebook with the customers to call, ranked by value, becomes a PDF that arrives by email on Monday morning. An alarm flags a customer entering the high band.
Python function
import numpy as np
import pandas as pd
def transform(inputs, params, ctx):
df = inputs["rows"]
df["order_date"] = pd.to_datetime(df["order_date"])
recent = df["order_date"] > df["order_date"].max() - pd.Timedelta(days=90)
share = 90 / 365
year = df.groupby(["customer_code", "sales_rep"], as_index=False).agg(
orders_year=("order_number", "nunique"), spend_year=("net_amount", "sum"))
last_90 = df[recent].groupby("customer_code", as_index=False).agg(
orders_90d=("order_number", "nunique"), spend_90d=("net_amount", "sum"))
out = year.merge(last_90, on="customer_code", how="left").fillna(0)
expected = (out["orders_year"] * share).replace(0, np.nan)
out["frequency_drop"] = (1 - out["orders_90d"] / expected).clip(0, 1)
expected_spend = (out["spend_year"] * share).replace(0, np.nan)
out["spend_drop"] = (1 - out["spend_90d"] / expected_spend).clip(0, 1)
weight = params["frequency_weight"]
out["risk"] = (weight * out["frequency_drop"]
+ (1 - weight) * out["spend_drop"]).fillna(0).round(2)
out["band"] = np.where(out["risk"] >= params["threshold"], "high", "normal")
return {"rows": out}- The data it needs
- Orders and order lines per customer over the last twelve months, from the ERP on SQL Server
- Customers, assigned sales rep and region from Salesforce
- Channel (wholesale or large retail) and terms, from an Excel file
More cases in this line
All use cases- Margins and management accountingInvoices and costs sit in the ERP, customers and sales reps in the CRM, the budget in a spreadsheet. In Muvia they become one margin by customer and by product, with the Monday report and an alarm when the numbers drift from budget.
- Sales and pipelineThe CRM knows what is being negotiated; the ERP knows what was ordered and invoiced. Muvia joins them: pipeline and conversion with one definition, the customers who are ordering less, and Athena answering the sales team's questions.
- Month-end close and budget variancesThe ledger sits in the ERP, the budget in a spreadsheet, payroll costs with another provider. In Muvia they become one monthly income statement per business unit, with an EBITDA bridge against budget and the close commentary arriving as a PDF on day three.
Bring us a question you can't answer today.
We start from a real question your business has and walk the path from source to dashboard with your systems, not a demo dataset.