Shipping Metrics & Calculations
This page explains how each shipping KPI shown on the Shipping Dashboard is calculated.
Date Ranges
The dashboard uses two fixed rolling windows:
| Window | Description |
|---|---|
| Current period | Today − 30 days → today |
| Previous period | Today − 60 days → today − 31 days |
Methods in ShippingDashboardChartHelpers:
getCurrent30DayDates()— returns[Carbon $start, Carbon $end]getPrevious30DayDates()— returns the preceding 30-day range
Average Shipping Time
Source: ShipStationOrder records where ship_date IS NOT NULL
Formula:
AVG(DATEDIFF(ship_date, order_date))
Only orders with both order_date and ship_date populated contribute to the average.
Method: getAverageShippingTimeForPeriod(string $groupBy, array $dates): float
Trend: An increase period-over-period is considered bad (shipping is taking longer).
Order Complexity
Source: ShipStationOrderItem joined to ShipStationOrder
Formula:
AVG(items_per_order) = SUM(items) / COUNT(DISTINCT order_id)
Method: getAvgItemsPerOrderForPeriod(string $groupBy, array $dates): float
Trend: An increase is considered bad (more complex orders take longer to pick/pack).
On-Time Delivery Rate
Source: ShipStationOrder records where shipby_date IS NOT NULL and ship_date IS NOT NULL
Formula:
on_time_rate = COUNT(orders WHERE ship_date <= shipby_date)
/ COUNT(orders WHERE shipby_date IS NOT NULL)
× 100
Method: getOnTimeDeliveryRateForPeriod(string $groupBy, array $dates): float
Trend: A decrease is considered bad (fewer orders being shipped on time).
Change Calculation
For each metric, the period-over-period change is computed as:
change(%) = ((current - previous) / previous) × 100
If previous == 0, change is null and direction is null (no comparison available).
Caching
The ShippingDashboard page uses Illuminate\Support\Facades\Cache to cache metric results. This avoids expensive aggregation queries on every page load. Cache TTL is configurable in the page class. Clear the cache after importing historical ShipStation data with:
php artisan cache:clear