Analytics, Bulk Operations & Webhooks
Advanced Orders features for reporting, high-volume operations, and external integrations.
Analytics
The OrderAnalyticsService provides real-time metrics with PostgreSQL materialized views for performance at scale.
All analytics endpoints accept from and to query parameters for date range filtering.
Dashboard Metrics
GET /api/v1/orders/analytics/dashboard?from=2026-03-01&to=2026-03-31
Returns total orders, revenue, average order value, unique customers, and breakdowns by status and payment status.
Revenue Time Series
GET /api/v1/orders/analytics/revenue?from=2026-03-01&to=2026-03-31
Returns daily order counts and revenue.
Other Analytics Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/orders/analytics/fulfillment |
Delivery, cancellation, and RTO rates |
GET |
/api/v1/orders/analytics/sources |
Orders and revenue by source module |
GET |
/api/v1/orders/analytics/products |
Top products by quantity and revenue |
GET |
/api/v1/orders/analytics/cod-vs-prepaid |
COD vs prepaid count and revenue split |
Service Usage
use Modules\Orders\App\Services\OrderAnalyticsService;
$analytics = app(OrderAnalyticsService::class);
$from = '2026-03-01';
$to = '2026-03-31';
$metrics = $analytics->getDashboardMetrics($from, $to);
$series = $analytics->getRevenueTimeSeries($from, $to);
$sources = $analytics->getSourceBreakdown($from, $to);
$fulfillment = $analytics->getFulfillmentMetrics($from, $to);
$split = $analytics->getCodVsPrepaid($from, $to);
$products = $analytics->getTopProducts($from, $to, 10);
Materialized Views
For high-traffic tenants, pre-computed analytics are refreshed every 15 minutes via RefreshAnalyticsViewsJob:
| View | Purpose |
|---|---|
mv_daily_order_stats |
Pre-aggregated daily metrics (orders, revenue, AOV, COD/prepaid split) |
mv_order_source_stats |
Per-source daily metrics |
Views use REFRESH MATERIALIZED VIEW CONCURRENTLY with unique indexes for non-blocking reads during refresh.
Bulk Operations
High-volume operations with queued processing and progress tracking.
CSV Import
POST /api/v1/orders/bulk/import
Content-Type: multipart/form-data
file: orders.csv
source: csv-import
CSV columns: order_number, customer_phone (required*), customer_email (required*), customer_first_name, customer_last_name, item_name (required), item_quantity (required), item_price (required), item_sku, total, payment_status, status, notes. *Phone or email required.
Processing details:
- Parsed in 500-row chunks via
Bus::batch() - Uses PostgreSQL
INSERT ... ON CONFLICT DO UPDATEfor idempotent upserts - Real-time progress via Laravel Reverb WebSockets
- Cancellable between chunks
Check Import Status
GET /api/v1/orders/bulk/import/{importId}
CSV Export
POST /api/v1/orders/bulk/export
{
"filters": { "status": "delivered", "date_from": "2026-01-01", "date_to": "2026-03-01" },
"columns": ["order_number", "customer_name", "total", "status", "created_at"]
}
Uses cursor-based streaming for memory efficiency.
Bulk Actions
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/orders/bulk/status |
Update status for multiple orders |
POST |
/api/v1/orders/bulk/ship |
Create shipments from tracking data |
POST |
/api/v1/orders/bulk/cancel |
Cancel multiple orders with reason |
Queue Configuration
Add dedicated supervisors in config/horizon.php:
'supervisor-imports' => [
'connection' => 'redis',
'queue' => ['imports'],
'maxProcesses' => 2,
'timeout' => 600,
],
'supervisor-exports' => [
'connection' => 'redis',
'queue' => ['exports'],
'maxProcesses' => 2,
'timeout' => 300,
],
Outbound Webhooks
Register HTTP endpoints to receive real-time order event notifications.
Creating an Endpoint
POST /api/v1/order-webhooks
{
"url": "https://yourapp.com/webhook/orders",
"secret": "whsec_your_signing_secret",
"events": ["order.created", "order.status_changed", "order.delivered"],
"is_active": true
}
Webhook Payload
{
"event": "order.status_changed",
"payload": {
"order_id": "uuid",
"order_number": "ORD-20260305-A1B2",
"old_status": "pending",
"new_status": "confirmed"
},
"timestamp": "2026-03-05T10:30:00+00:00"
}
Signature Verification
Requests include an X-Webhook-Signature header (HMAC-SHA256 of the body using the endpoint secret). Verify in your receiver:
import hmac, hashlib
signature = request.headers['X-Webhook-Signature']
expected = hmac.new(secret.encode(), request.body, hashlib.sha256).hexdigest()
assert hmac.compare_digest(signature, expected)
Failure Handling
- Failed deliveries retry 3 times with 60-second backoff
- Auto-disabled after 10 consecutive failures
- All deliveries logged with response status and duration
Notification Rules
Configure automatic notifications triggered by order events.
POST /api/v1/order-notification-rules
{
"name": "Order Shipped SMS",
"event": "order.fulfilled",
"channel": "sms",
"recipient_type": "customer",
"template": "Hi {{customer_name}}, your order #{{order_number}} has been shipped! Track: {{tracking_url}}",
"conditions": {},
"is_active": true
}
Supported Channels
| Channel | Delivery |
|---|---|
sms |
Via SMS provider module |
whatsapp |
Via WhatsApp channel module |
email |
Via email service |
in_app |
Via NotificationService |
Template Placeholders
{{order_number}}, {{customer_name}}, {{total}}, {{status}}, {{tracking_url}}, {{return_number}}
Test Send
POST /api/v1/order-notification-rules/{rule}/test
Custom Fields
Define tenant-specific fields that appear on orders.
| Type | Description |
|---|---|
text |
Free text input |
number |
Numeric input |
select |
Dropdown with predefined options |
boolean |
Toggle (yes/no) |
date |
Date picker |
POST /api/v1/order-custom-fields
{
"field_key": "priority_level",
"field_label": "Priority Level",
"field_type": "select",
"options": ["low", "normal", "high", "urgent"],
"is_required": false,
"is_filterable": true,
"sort_order": 1
}
Values are stored in the order's custom_fields JSONB column. Fields marked is_filterable can be used in order list queries.