# December 2025 KPI Scorecard

| KPI | Dec actual | Target | Variance | Var % | Nov actual | Status |
|---|---|---|---|---|---|---|
| Revenue | $826,751 | $823,600 | +3,151 | +0.4% | $898,680 | On/above target |
| Gross margin % | 26.06% | 26.00% | +0.06 pp | +0.2% | 25.79% | On/above target |
| Days sales outstanding | 51.2 | 45.0 | +6.20 | +13.8% | 48.6 | Miss |
| On-time delivery % | 93.30% | 95.00% | -1.70 pp | -1.8% | 93.70% | Miss |
| Order fill rate % | 97.60% | 97.00% | +0.60 pp | +0.6% | 97.40% | On/above target |
| Active customers | 40 | 42 | -2 | -4.8% | 41 | Miss |
| Inventory turns | 5.33 | 6.50 | -1.17 | -18.0% | 6.67 | Miss |
| Opex % of revenue | 25.11% | 25.25% | -0.14 pp | -0.6% | 22.57% | On/above target |

Four KPIs hit target and four missed. Status accounts for direction: for DSO and opex %, lower is better.

- **Hit:** revenue, gross margin, order fill rate and opex % of revenue.
- **Missed:**
  - Inventory turns is the largest miss, 18% below target and down from 6.67 in November.
  - DSO is 6.2 days over target and has worsened from 48.6 in November.
  - On-time delivery is 1.7 pp short of target.
  - Active customers is 2 below target.
- **Opex %:** it rose from 22.57% in November to 25.11%, but it is still just under the 25.25% budget ratio.

I computed every figure with `scorecard.py` and read them straight from the CSV. I did not write the output to a file because the redirect was blocked. The script is in the working directory if you want to save it. Rerun it with `python3 scorecard.py > december_kpi_scorecard.md`.