Calculate DSO: Days Sales Outstanding Calculator & Guide
:root {
–primary-color: #004a99;
–success-color: #28a745;
–background-color: #f8f9fa;
–text-color: #333;
–border-color: #ddd;
–card-background: #ffffff;
–shadow: 0 2px 5px rgba(0,0,0,0.1);
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(–text-color);
background-color: var(–background-color);
margin: 0;
padding: 0;
}
.container {
max-width: 1000px;
margin: 20px auto;
padding: 20px;
background-color: var(–card-background);
border-radius: 8px;
box-shadow: var(–shadow);
}
h1, h2, h3 {
color: var(–primary-color);
}
h1 {
text-align: center;
margin-bottom: 30px;
}
.calculator-wrapper {
background-color: var(–card-background);
padding: 25px;
border-radius: 8px;
box-shadow: var(–shadow);
margin-bottom: 40px;
}
.calculator-wrapper h2 {
text-align: center;
margin-bottom: 25px;
color: var(–primary-color);
}
.input-group {
margin-bottom: 20px;
display: flex;
flex-direction: column;
}
.input-group label {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: var(–primary-color);
}
.input-group input[type="number"],
.input-group input[type="text"],
.input-group select {
width: calc(100% – 22px); /* Account for padding and border */
padding: 10px;
border: 1px solid var(–border-color);
border-radius: 4px;
font-size: 1rem;
box-sizing: border-box;
}
.input-group input[type="number"]:focus,
.input-group input[type="text"]:focus,
.input-group select:focus {
outline: none;
border-color: var(–primary-color);
box-shadow: 0 0 0 2px rgba(0, 74, 153, 0.2);
}
.input-group .helper-text {
font-size: 0.85em;
color: #666;
margin-top: 5px;
}
.error-message {
color: #dc3545;
font-size: 0.85em;
margin-top: 5px;
display: none; /* Hidden by default */
}
.button-group {
display: flex;
justify-content: space-between;
margin-top: 25px;
gap: 10px;
}
.button-group button,
.button-group input[type="button"] {
padding: 12px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
font-weight: bold;
transition: background-color 0.3s ease;
flex-grow: 1;
}
#calculateBtn {
background-color: var(–primary-color);
color: white;
}
#calculateBtn:hover {
background-color: #003366;
}
#resetBtn, #copyBtn {
background-color: #6c757d;
color: white;
}
#resetBtn:hover, #copyBtn:hover {
background-color: #5a6268;
}
#result-container {
margin-top: 30px;
padding: 20px;
background-color: var(–primary-color);
color: white;
border-radius: 5px;
text-align: center;
box-shadow: var(–shadow);
}
#result-container h3 {
color: white;
margin-bottom: 15px;
}
#mainResult {
font-size: 2.5em;
font-weight: bold;
margin-bottom: 10px;
}
#formulaExplanation {
font-size: 0.9em;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid rgba(255, 255, 255, 0.3);
}
.intermediate-results {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 20px;
flex-wrap: wrap;
}
.intermediate-results > div {
background-color: rgba(255, 255, 255, 0.15);
padding: 10px 15px;
border-radius: 4px;
text-align: center;
}
.intermediate-results span {
display: block;
font-size: 1.8em;
font-weight: bold;
}
.intermediate-results p {
font-size: 0.9em;
margin: 0;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 30px;
margin-bottom: 30px;
box-shadow: var(–shadow);
}
th, td {
padding: 12px 15px;
text-align: left;
border: 1px solid var(–border-color);
}
thead {
background-color: var(–primary-color);
color: white;
}
tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
caption {
font-size: 1.1em;
font-weight: bold;
color: var(–primary-color);
margin-bottom: 10px;
text-align: left;
}
.chart-container {
margin-top: 30px;
text-align: center;
background-color: var(–card-background);
padding: 20px;
border-radius: 8px;
box-shadow: var(–shadow);
}
.chart-container canvas {
max-width: 100%;
height: auto;
}
.chart-caption {
font-size: 0.9em;
color: #666;
margin-top: 10px;
}
.article-content {
margin-top: 40px;
background-color: var(–card-background);
padding: 30px;
border-radius: 8px;
box-shadow: var(–shadow);
}
.article-content h2, .article-content h3 {
margin-top: 25px;
margin-bottom: 15px;
}
.article-content p {
margin-bottom: 15px;
}
.faq-item {
margin-bottom: 15px;
}
.faq-item strong {
color: var(–primary-color);
cursor: pointer;
display: block;
margin-bottom: 5px;
}
.faq-item p {
margin-left: 20px;
display: none; /* Hidden by default */
background-color: var(–background-color);
padding: 10px;
border-left: 3px solid var(–primary-color);
}
.internal-links {
margin-top: 30px;
background-color: var(–card-background);
padding: 25px;
border-radius: 8px;
box-shadow: var(–shadow);
}
.internal-links h3 {
margin-bottom: 20px;
}
.internal-links ul {
list-style: none;
padding: 0;
}
.internal-links li {
margin-bottom: 15px;
border-bottom: 1px dashed var(–border-color);
padding-bottom: 10px;
}
.internal-links li:last-child {
border-bottom: none;
}
.internal-links a {
color: var(–primary-color);
text-decoration: none;
font-weight: bold;
}
.internal-links a:hover {
text-decoration: underline;
}
.internal-links p {
font-size: 0.9em;
color: #555;
margin-top: 5px;
}
@media (max-width: 768px) {
.container {
margin: 10px;
padding: 15px;
}
.button-group {
flex-direction: column;
}
.intermediate-results {
flex-direction: column;
gap: 15px;
}
.intermediate-results > div {
width: 80%;
margin: 0 auto;
}
th, td {
padding: 8px 10px;
font-size: 0.9em;
}
}
Calculate DSO: Days Sales Outstanding Calculator & Guide
Days Sales Outstanding (DSO) Calculator
Your Days Sales Outstanding (DSO):
—
Key Assumptions:
Accounts Receivable:
Net Credit Sales:
Period: Days
Understanding DSO Benchmarks
Typical DSO Ranges by Industry
| Industry |
Typical DSO Range |
Interpretation |
| Technology |
35-45 Days |
Generally efficient collections. |
| Manufacturing |
45-60 Days |
Standard collection cycles. |
| Retail (B2B) |
30-45 Days |
Focus on quick payment terms. |
| Services |
40-55 Days |
Varies based on project complexity. |
| Healthcare |
50-70 Days |
Complex billing and insurance processes. |
Note: These are general benchmarks and can vary significantly. Analyze your specific business context.
DSO Trend Over Time
Comparison of DSO against Sales Per Day over the last few periods.
What is Days Sales Outstanding (DSO)?
Days Sales Outstanding, commonly known as DSO, is a key financial metric that measures the average number of days it takes for a company to collect payments owed by its customers after a sale has been made. In simpler terms, it tells you how quickly your business is turning its credit sales into cash. A lower DSO generally indicates that a company is efficient in collecting its debts, which positively impacts its cash flow and liquidity. Conversely, a high DSO might signal issues with credit policies, collection processes, or the financial health of the company's customers.
Who Should Use DSO?
DSO is a critical metric for almost any business that extends credit to its customers. This includes:
- Businesses with Credit Sales: If you sell goods or services on payment terms (e.g., Net 30, Net 60), DSO is essential for monitoring your accounts receivable.
- Financial Analysts: To assess a company's operational efficiency and financial health.
- Credit Managers: To evaluate the effectiveness of credit and collection policies.
- Small Business Owners: To ensure consistent cash flow for day-to-day operations.
- Investors: To gauge the working capital management of a company.
Common Misconceptions About DSO
One common misconception is that the lowest possible DSO is always the best. While a low DSO is generally favorable, an extremely low DSO could indicate overly strict credit policies that might be deterring potential sales, or perhaps that the company is not maximizing its credit terms to support customer growth. Another misconception is that DSO is a static number; it fluctuates based on sales cycles, customer payment habits, and economic conditions. It's best viewed as a trend over time rather than a single point in time.
DSO Formula and Mathematical Explanation
The calculation of Days Sales Outstanding is straightforward and involves three main components: total accounts receivable, net credit sales over a specific period, and the number of days in that period.
The Core DSO Formula:
The primary formula to calculate DSO is:
DSO = (Accounts Receivable / Net Credit Sales) * Period in Days
Step-by-Step Derivation and Variable Explanations:
- Calculate Average Accounts Receivable: While the calculator uses ending Accounts Receivable for simplicity, a more robust calculation often uses the average of beginning and ending Accounts Receivable for the period. However, for many analyses, ending AR is sufficient.
- Determine Net Credit Sales: This is the total value of all sales made on credit during the chosen period (e.g., month, quarter, year), after deducting returns, allowances, and discounts. It's crucial to use *credit* sales, not total sales, as DSO specifically relates to collecting payment for credit transactions.
- Calculate Average Daily Sales: Divide the Net Credit Sales for the period by the number of days in that period. This gives you the average revenue generated per day from credit sales.
Average Daily Sales = Net Credit Sales / Period in Days
- Calculate DSO: Divide the total Accounts Receivable (outstanding invoices) by the Average Daily Sales. This result represents the average number of days it takes to collect receivables.
DSO = Accounts Receivable / Average Daily Sales
Substituting the Average Daily Sales formula:
DSO = Accounts Receivable / (Net Credit Sales / Period in Days)
Which simplifies to the primary formula:
DSO = (Accounts Receivable / Net Credit Sales) * Period in Days
Key Intermediate Calculations:
- Average Collection Period: This is essentially the DSO itself, representing the average time to collect outstanding invoices.
- Sales Per Day: This is the Average Daily Sales calculated in step 3. It shows how much revenue is generated on an average day through credit sales.
- Receivables to Sales Ratio: This ratio indicates how much of the daily sales is currently outstanding in accounts receivable. A higher ratio suggests that more sales are remaining uncollected relative to daily sales volume.
Receivables to Sales Ratio = Accounts Receivable / Net Credit Sales
Variables Table:
DSO Calculation Variables
| Variable |
Meaning |
Unit |
Typical Range |
| Accounts Receivable (AR) |
Total amount of money owed to the company by its customers for goods or services already delivered but not yet paid for. |
Currency (e.g., $, €, £) |
Varies greatly by business size and sales volume. Positive value. |
| Net Credit Sales (NCS) |
Total sales made on credit during a specific period, after accounting for returns, allowances, and discounts. |
Currency (e.g., $, €, £) |
Varies greatly by business size and sales volume. Positive value. |
| Period in Days |
The length of the time period over which Net Credit Sales are measured (e.g., 30 for a month, 91 for a quarter, 365 for a year). |
Days |
Typically 30, 60, 90, 365. Positive integer. |
| DSO |
Days Sales Outstanding. The average number of days required to collect payment after a sale is made. |
Days |
Depends on industry and company policy. Typically 20-60 days. |
| Average Daily Sales (ADS) |
Average revenue generated per day from credit sales during the period. |
Currency per Day |
Net Credit Sales / Period in Days |
| Receivables to Sales Ratio |
Ratio of outstanding receivables to total credit sales for the period. |
Ratio (e.g., 0.5) |
Positive value. Indicates proportion of sales still outstanding. |
Practical Examples (Real-World Use Cases)
Example 1: A Growing Software Company
A software-as-a-service (SaaS) company, "CloudSync Solutions," is analyzing its performance for the last quarter.
- Accounts Receivable (End of Quarter): $120,000
- Net Credit Sales (Last Quarter): $900,000
- Period in Days: 90 (for the quarter)
Calculation:
- Average Daily Sales = $900,000 / 90 days = $10,000 per day
- DSO = ($120,000 / $900,000) * 90 days = 0.1333 * 90 days = 12 days
- Receivables to Sales Ratio = $120,000 / $900,000 = 0.1333
Interpretation: CloudSync Solutions has a DSO of 12 days. This is exceptionally low, suggesting very efficient collections. Given their typical payment terms (often monthly subscriptions), this indicates customers are paying promptly. This strong cash conversion cycle supports their growth initiatives.
Example 2: A Manufacturing Firm
"MetalWorks Inc." is reviewing its annual performance.
- Accounts Receivable (End of Year): $850,000
- Net Credit Sales (Last Year): $6,000,000
- Period in Days: 365 (for the year)
Calculation:
- Average Daily Sales = $6,000,000 / 365 days = $16,438.36 per day
- DSO = ($850,000 / $6,000,000) * 365 days = 0.1417 * 365 days = 51.7 days
- Receivables to Sales Ratio = $850,000 / $6,000,000 = 0.1417
Interpretation: MetalWorks Inc. has a DSO of approximately 52 days. This falls within the typical range for manufacturing. It suggests that, on average, it takes about 52 days for the company to receive payment after a sale. Management should compare this to their stated payment terms (e.g., Net 60) and industry benchmarks to ensure efficiency.
How to Use This DSO Calculator
Our Days Sales Outstanding calculator is designed for ease of use. Follow these simple steps to get your DSO:
Step-by-Step Instructions:
- Enter Accounts Receivable: Input the total amount of money your customers owe you at the end of the specific period you are analyzing. This is found on your balance sheet.
- Enter Net Credit Sales: Input the total revenue generated from sales made on credit during that same period. Ensure this figure excludes cash sales, returns, and allowances.
- Specify Period in Days: Enter the number of days in the period you are analyzing. Common values are 30 (for a month), 90 (for a quarter), or 365 (for a year).
- Click 'Calculate DSO': Press the button to see your calculated DSO.
How to Read Your Results:
- Main Result (DSO): This is your primary Days Sales Outstanding figure. A lower number is generally better, indicating faster cash collection.
- Average Collection Period: This is another term for DSO and reinforces the time frame for collections.
- Sales Per Day: This intermediate value shows your average daily revenue from credit sales, providing context for your DSO.
- Receivables to Sales Ratio: This ratio helps understand how your outstanding receivables compare to your sales volume.
Decision-Making Guidance:
Use your calculated DSO to make informed business decisions:
- Compare to Terms: Is your DSO higher than your stated payment terms (e.g., Net 30)? If so, you may need to tighten credit policies or improve collection efforts.
- Benchmark: Compare your DSO against industry averages and historical data. Significant deviations warrant investigation.
- Cash Flow Planning: A predictable DSO helps in forecasting cash inflows more accurately.
- Identify Issues: A rising DSO trend can be an early warning sign of potential cash flow problems or customer financial distress.
Use the 'Reset' button to clear fields and start over, and the 'Copy Results' button to easily share your findings.
Key Factors That Affect DSO Results
Several factors can influence a company's Days Sales Outstanding, impacting its cash conversion cycle and overall financial health. Understanding these is crucial for effective management:
- Credit Policy Stringency: A company's credit policies dictate the terms offered to customers (e.g., Net 30, Net 60) and the criteria for approving credit. Stricter policies and shorter terms generally lead to lower DSO, but may also limit sales volume. Looser policies can increase sales but risk higher DSO and bad debt.
- Collection Effectiveness: The efficiency of a company's accounts receivable department plays a significant role. Timely invoicing, prompt follow-ups on overdue accounts, and effective collection strategies directly reduce the time it takes to collect payments, thus lowering DSO.
- Customer Payment Habits: The payment behavior of your customer base is a major determinant. Some industries or customer segments inherently pay slower than others due to their own operational cycles or financial constraints. Understanding your key customers' payment trends is vital.
- Economic Conditions: During economic downturns, customers may extend their payment times, leading to an increase in DSO across many businesses. Conversely, a strong economy often correlates with faster payments and lower DSO.
- Industry Norms and Payment Terms: Different industries have established norms for payment terms and collection times. For example, industries with complex billing processes (like healthcare) often have higher DSOs than those with simple, transactional sales (like some retail).
- Sales Volume and Seasonality: Significant fluctuations in sales volume, especially during peak seasons or promotional periods, can temporarily skew DSO. A surge in sales might lead to a temporary increase in receivables before payments catch up.
- Invoicing Accuracy and Timeliness: Errors on invoices or delays in sending them out can cause disputes or postponed payments, thereby increasing DSO. Ensuring invoices are accurate and dispatched promptly is a fundamental aspect of efficient collections.
- Dispute Resolution Process: When customers have issues with products or services, they may withhold payment. An inefficient or slow dispute resolution process can prolong the period receivables remain outstanding.
Frequently Asked Questions (FAQ)
What is considered a "good" DSO?
A "good" DSO is relative and depends heavily on your industry, business model, and stated credit terms. Generally, a DSO equal to or lower than your average payment terms (e.g., if terms are Net 30, a DSO below 30 is good) is considered efficient. Always compare against industry benchmarks.
Should I use total sales or credit sales for DSO calculation?
You should always use Net Credit Sales for the DSO calculation. DSO specifically measures how quickly you collect money from sales made on credit, not cash sales.
Does DSO apply to businesses with no credit sales?
No, DSO is only relevant for businesses that extend credit to their customers. If you only accept cash, upfront payments, or immediate electronic transfers, DSO is not applicable.
How often should I calculate DSO?
It's best practice to calculate DSO regularly, typically monthly or quarterly. This allows you to track trends, identify issues early, and monitor the effectiveness of your collection strategies.
What's the difference between DSO and Average Collection Period?
There is no difference. Days Sales Outstanding (DSO) and Average Collection Period are terms used interchangeably to refer to the same metric: the average time it takes to collect payment after a sale.
What if my Accounts Receivable is $0?
If your Accounts Receivable is $0, your DSO will be 0 days, assuming positive net credit sales. This indicates highly efficient collections for that period.
What if my Net Credit Sales is $0?
If your Net Credit Sales is $0 for the period, the DSO formula cannot be calculated (division by zero). This situation implies no credit sales occurred during the period, making DSO irrelevant for that specific timeframe.
Can DSO be negative?
No, DSO cannot be negative. Accounts Receivable and Net Credit Sales are typically positive values, and the period in days is always positive. Therefore, the result will always be zero or positive.
How does DSO impact working capital?
A lower DSO means faster collection of cash, which improves working capital. This frees up cash that can be used for operations, investments, or reducing debt. Conversely, a high DSO ties up cash in receivables, negatively impacting working capital.
Related Tools and Internal Resources
function calculateDSO() {
var arInput = document.getElementById("accountsReceivable");
var ncsInput = document.getElementById("netCreditSales");
var daysInput = document.getElementById("periodDays");
var arError = document.getElementById("accountsReceivableError");
var ncsError = document.getElementById("netCreditSalesError");
var daysError = document.getElementById("periodDaysError");
var resultContainer = document.getElementById("result-container");
var mainResult = document.getElementById("mainResult");
var avgCollectionPeriod = document.getElementById("avgCollectionPeriod").getElementsByTagName('span')[0];
var salesPerDay = document.getElementById("salesPerDay").getElementsByTagName('span')[0];
var receivablesToSalesRatio = document.getElementById("receivablesToSalesRatio").getElementsByTagName('span')[0];
var formulaExplanation = document.getElementById("formulaExplanation");
var assumptionAR = document.getElementById("assumptionAR");
var assumptionNCS = document.getElementById("assumptionNCS");
var assumptionPeriod = document.getElementById("assumptionPeriod");
// Reset errors
arError.style.display = "none";
ncsError.style.display = "none";
daysError.style.display = "none";
var isValid = true;
var accountsReceivable = parseFloat(arInput.value);
var netCreditSales = parseFloat(ncsInput.value);
var periodDays = parseInt(daysInput.value);
if (isNaN(accountsReceivable) || accountsReceivable < 0) {
arError.textContent = "Please enter a valid non-negative number for Accounts Receivable.";
arError.style.display = "block";
isValid = false;
}
if (isNaN(netCreditSales) || netCreditSales <= 0) {
ncsError.textContent = "Please enter a valid positive number for Net Credit Sales.";
ncsError.style.display = "block";
isValid = false;
}
if (isNaN(periodDays) || periodDays <= 0) {
daysError.textContent = "Please enter a valid positive number for Period in Days.";
daysError.style.display = "block";
isValid = false;
}
if (isValid) {
var averageDailySales = netCreditSales / periodDays;
var dso = (accountsReceivable / netCreditSales) * periodDays;
var ratio = accountsReceivable / netCreditSales;
// Rounding to two decimal places for display
var formattedDSO = dso.toFixed(2);
var formattedAvgCollection = dso.toFixed(2); // Same as DSO
var formattedSalesPerDay = averageDailySales.toFixed(2);
var formattedRatio = ratio.toFixed(2);
mainResult.textContent = formattedDSO + " Days";
avgCollectionPeriod.textContent = formattedAvgCollection;
salesPerDay.textContent = "$" + formattedSalesPerDay;
receivablesToSalesRatio.textContent = formattedRatio;
assumptionAR.textContent = "$" + accountsReceivable.toFixed(2);
assumptionNCS.textContent = "$" + netCreditSales.toFixed(2);
assumptionPeriod.textContent = periodDays;
formulaExplanation.innerHTML = "
Formula: (Accounts Receivable / Net Credit Sales) * Period in Days" +
"This calculates the average number of days it takes to collect outstanding credit payments.";
resultContainer.style.display = "block";
updateChart(formattedDSO, formattedSalesPerDay, periodDays); // Pass relevant values for chart
} else {
resultContainer.style.display = "none";
}
}
function resetCalculator() {
document.getElementById("accountsReceivable").value = "";
document.getElementById("netCreditSales").value = "";
document.getElementById("periodDays").value = "30";
document.getElementById("accountsReceivableError").style.display = "none";
document.getElementById("netCreditSalesError").style.display = "none";
document.getElementById("periodDaysError").style.display = "none";
document.getElementById("result-container").style.display = "none";
// Optionally clear chart or reset to defaults
updateChart(0, 0, 30);
}
function copyResults() {
var mainResultText = document.getElementById("mainResult").textContent;
var avgCollSpan = document.getElementById("avgCollectionPeriod").getElementsByTagName('span')[0].textContent;
var salesPerDaySpan = document.getElementById("salesPerDay").getElementsByTagName('span')[0].textContent;
var ratioSpan = document.getElementById("receivablesToSalesRatio").getElementsByTagName('span')[0].textContent;
var formula = document.getElementById("formulaExplanation").innerText.replace("Formula: ", "");
var assumptionARText = document.getElementById("assumptionAR").textContent;
var assumptionNCText = document.getElementById("assumptionNCS").textContent;
var assumptionPeriodText = document.getElementById("assumptionPeriod").textContent;
var resultsText = "DSO Calculation Results:\n\n" +
"Days Sales Outstanding (DSO): " + mainResultText + "\n" +
"Average Collection Period: " + avgCollSpan + "\n" +
"Sales Per Day: " + salesPerDaySpan + "\n" +
"Receivables to Sales Ratio: " + ratioSpan + "\n\n" +
"Assumptions:\n" +
"Accounts Receivable: " + assumptionARText + "\n" +
"Net Credit Sales: " + assumptionNCText + "\n" +
"Period: " + assumptionPeriodText + " Days\n\n" +
"Formula: " + formula;
var textArea = document.createElement("textarea");
textArea.value = resultsText;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
alert("Results copied to clipboard!");
} catch (err) {
console.error('Failed to copy: ', err);
alert("Failed to copy results. Please copy manually.");
}
document.body.removeChild(textArea);
}
function toggleFaq(element) {
var content = element.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
}
// Charting Logic
var dsoChart; // Declare chart variable globally
function updateChart(currentDso, currentSalesPerDay, periodDays) {
var ctx = document.getElementById('dsoTrendChart').getContext('2d');
// Simulate historical data for demonstration
var historicalPeriods = 5;
var historicalDso = [];
var historicalSalesPerDay = [];
var labels = [];
var baseAR = parseFloat(document.getElementById("accountsReceivable").value) || 120000;
var baseNCS = parseFloat(document.getElementById("netCreditSales").value) || 900000;
var baseDays = parseInt(document.getElementById("periodDays").value) || 90;
var baseAvgDailySales = baseNCS / baseDays;
var baseDSO = (baseAR / baseNCS) * baseDays;
for (var i = historicalPeriods – 1; i >= 0; i–) {
var periodFactor = historicalPeriods – i; // Simulate a trend
var simulatedAR = baseAR * (1 + (i – 2) * 0.05); // Slight variation
var simulatedNCS = baseNCS * (1 + (i – 2) * 0.08); // Slight variation
var simulatedPeriod = baseDays; // Assuming same period length for simplicity
var simulatedAvgDailySales = simulatedNCS / simulatedPeriod;
var simulatedDSO = (simulatedAR / simulatedNCS) * simulatedPeriod;
labels.push("Period " + periodFactor);
historicalDso.push(simulatedDSO.toFixed(2));
historicalSalesPerDay.push(simulatedAvgDailySales.toFixed(2));
}
// Add current period data
labels.push("Current");
historicalDso.push(currentDso);
historicalSalesPerDay.push(currentSalesPerDay);
// Destroy existing chart if it exists
if (dsoChart) {
dsoChart.destroy();
}
dsoChart = new Chart(ctx, {
type: 'bar', // Using bar chart for better comparison of two series
data: {
labels: labels,
datasets: [{
label: 'DSO (Days)',
data: historicalDso,
backgroundColor: 'rgba(0, 74, 153, 0.6)', // Primary color
borderColor: 'rgba(0, 74, 153, 1)',
borderWidth: 1,
yAxisID: 'y-axis-dso' // Assign to DSO axis
}, {
label: 'Avg Daily Sales ($)',
data: historicalSalesPerDay,
backgroundColor: 'rgba(40, 167, 69, 0.6)', // Success color
borderColor: 'rgba(40, 167, 69, 1)',
borderWidth: 1,
yAxisID: 'y-axis-sales' // Assign to Sales axis
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
x: {
title: {
display: true,
text: 'Period'
}
},
'y-axis-dso': { // Configure DSO y-axis
type: 'linear',
position: 'left',
title: {
display: true,
text: 'Days Sales Outstanding (Days)'
},
ticks: {
beginAtZero: true,
callback: function(value) {
if (value % 10 === 0) return value; // Show multiples of 10
}
}
},
'y-axis-sales': { // Configure Sales y-axis
type: 'linear',
position: 'right',
title: {
display: true,
text: 'Average Daily Sales ($)'
},
ticks: {
beginAtZero: true,
callback: function(value) {
return '$' + value.toLocaleString(); // Format as currency
}
},
grid: {
drawOnChartArea: false, // Only draw grid lines for the left axis
}
}
},
plugins: {
tooltip: {
mode: 'index',
intersect: false
},
legend: {
position: 'top'
}
}
}
});
}
// Initial setup
document.getElementById("calculateBtn").onclick = calculateDSO;
document.getElementById("resetBtn").onclick = resetCalculator;
document.getElementById("copyBtn").onclick = copyResults;
// Trigger calculation on initial load if default values are present
document.addEventListener('DOMContentLoaded', function() {
calculateDSO(); // Calculate once on load with default values
});
// Add event listeners for input changes to update chart dynamically
document.getElementById("accountsReceivable").addEventListener('input', function() {
var currentDso = parseFloat(document.getElementById("mainResult").textContent) || 0;
var currentSalesPerDay = parseFloat(document.getElementById("salesPerDay").getElementsByTagName('span')[0].textContent.replace('$', ")) || 0;
var currentPeriod = parseInt(document.getElementById("periodDays").value) || 30;
updateChart(currentDso, currentSalesPerDay, currentPeriod);
});
document.getElementById("netCreditSales").addEventListener('input', function() {
var currentDso = parseFloat(document.getElementById("mainResult").textContent) || 0;
var currentSalesPerDay = parseFloat(document.getElementById("salesPerDay").getElementsByTagName('span')[0].textContent.replace('$', ")) || 0;
var currentPeriod = parseInt(document.getElementById("periodDays").value) || 30;
updateChart(currentDso, currentSalesPerDay, currentPeriod);
});
document.getElementById("periodDays").addEventListener('input', function() {
var currentDso = parseFloat(document.getElementById("mainResult").textContent) || 0;
var currentSalesPerDay = parseFloat(document.getElementById("salesPerDay").getElementsByTagName('span')[0].textContent.replace('$', ")) || 0;
var currentPeriod = parseInt(document.getElementById("periodDays").value) || 30;
updateChart(currentDso, currentSalesPerDay, currentPeriod);
});
// Basic chart library initialization (Chart.js) – MUST be included if not present globally
// In a real-world scenario, you'd load Chart.js from a CDN or locally.
// For this standalone HTML, we'll assume it's available or include a minimal mock.
// IMPORTANT: For this code to run, you NEED Chart.js library included in your HTML or before the script tag.
// For example:
// Mock Chart object if Chart.js is not loaded, to prevent errors during initial load
if (typeof Chart === 'undefined') {
var Chart = function() {
this.destroy = function() {};
};
console.warn("Chart.js not found. Chart functionality will be limited.");
}