Analytics - Services Documentation
Location: api/nextango/apps/analytics/services/
Last Updated: 2026-03-14
Overview
The Analytics domain owns two services: ActiveOperationsService surfaces live operational queues (pending pickups, in-transit shipments, pending transactions, open returns), and InfrastructureService aggregates sync pipeline health and system component status.
All other analytics data is retrieved by delegating to domain-owned services in transactions, products, users, promotions, and procurement. See the domain overview for the full mapping.
ActiveOperationsService
Location: api/nextango/apps/analytics/services/active_operations.py
Surfaces live operational queues for a single store. Each method returns a list of plain dicts so callers can serialize results without ORM awareness.
Constructor
service = ActiveOperationsService(store_id="uuid-or-sanity-id")
store_id accepts either the store's Django UUID primary key or its Sanity document ID. All queries use a combined Q(store__id=s) | Q(store__sanity_id=s) filter.
get_pending_pickups()
Returns PickupSchedule rows with status pending or ready for the store, ordered by scheduled_time.
Store is reached via: fulfillment → transaction → store.
Returns: list[dict]
[
{
"id": "uuid",
"status": "pending",
"scheduled_time": "2026-03-06T15:00:00Z",
"ready_at": null,
"customer_notified_at": null,
"preparation_notes": "Handle with care",
"fulfillment_id": "uuid",
"transaction_id": "uuid"
}
]
get_in_transit_shipments()
Returns Shipment rows with status shipped or in_transit, ordered by created_at descending.
Store is reached via: fulfillment → transaction → store.
Returns: list[dict]
[
{
"id": "uuid",
"status": "in_transit",
"carrier_name": "FedEx",
"tracking_number": "7489234908",
"shipped_at": "2026-03-05T10:00:00Z",
"fulfillment_id": "uuid"
}
]
get_pending_transactions()
Returns SaleTransaction rows with status pending or partially_paid, ordered by timestamp descending.
Includes expires_at so the dashboard can surface expiry warnings for layaway and pay-at-pickup orders.
Returns: list[dict]
[
{
"id": "uuid",
"transaction_id": "TXN-001",
"status": "pending",
"total_amount": "49.99",
"expires_at": "2026-03-06T14:00:00Z",
"timestamp": "2026-03-06T13:45:00Z"
}
]
expires_at is null for counter-sale transactions.
get_open_returns()
Returns Return rows with status pending, ordered by timestamp descending.
Store is reached via: originalSaleId → store.
Returns: list[dict]
[
{
"id": "uuid",
"return_id": "RTN-001",
"status": "pending",
"reason": "Defective item",
"timestamp": "2026-03-06T11:00:00Z",
"original_transaction_id": "uuid"
}
]
InfrastructureService
Location: api/nextango/apps/analytics/services/infrastructure.py
Aggregates sync pipeline stats and system health. All methods are safe to call — exceptions are caught and logged internally, never raised to the caller.
Used by GET /api/analytics/system/infrastructure/.
get_all(days=30)
Assembles the full infrastructure payload by calling all sub-methods. The days parameter controls the lookback window for all stats (minimum 7, maximum 365).
service = InfrastructureService()
data = service.get_all(days=30)
get_webhook_stats(days=30)
Aggregates WebhookEvent counts for the last N days. Covers inbound Sanity→Django traffic only.
Returns:
{
"total_received": 1240,
"processed": 1228,
"failed": 12,
"retrying": 0,
"avg_processing_ms": 145.3
}
avg_processing_ms is null when no completed events exist in the window.
get_sync_audit_stats(days=30)
Aggregates SyncAuditLog counts for the last N days. Covers both inbound (Sanity→Django) and outbound (Django→Sanity) sync operations.
Returns:
{
"inbound": {"total": 1240, "completed": 1228, "failed": 12},
"outbound": {"total": 320, "completed": 318, "failed": 2},
"combined": {"total": 1560, "failed": 14}
}
get_daily_throughput(days=30)
Daily sync volume for the last N days, merging WebhookEvent (inbound) and SyncAuditLog outbound rows by date.
Returns: list of {hour, inbound, outbound, failed} dicts, one per day that had any activity. Days with no activity do not appear.
The hour key holds a YYYY-MM-DD date string (named hour for frontend chart compatibility).
get_db_health()
Pings the PostgreSQL connection.
Returns: {"status": "ok"} or {"status": "error", "detail": "..."}
get_redis_health()
Checks Redis via Django's cache layer (cache.get('_health')).
Returns: {"status": "ok"} or {"status": "error", "detail": "..."}
get_celery_health()
Checks Celery worker availability via inspect.stats() with a 0.5-second timeout.
Returns:
{"status": "ok", "worker_count": 2}
# or
{"status": "unknown", "worker_count": null}
# or
{"status": "error", "detail": "..."}
Returns "unknown" (not "error") when the inspect call times out or returns no workers — this is normal for staging environments with no active workers.
CustomerAnalyticsService
Location: api/nextango/apps/users/analytics_service.py (delegated via analytics domain)
All methods accept store_id and date range (start_date, end_date) unless noted.
get_cohort_retention()
Monthly cohort retention table. Groups customers by their first-purchase month and tracks repurchase rates across subsequent months.
Returns: list of cohort objects
[
{
"cohort_month": "2026-01",
"cohort_size": 142,
"periods": [
{"period": 0, "retained": 142, "rate": 100.0},
{"period": 1, "retained": 61, "rate": 43.0},
{"period": 2, "retained": 38, "rate": 26.8}
]
}
]
Period 0 is always 100%. Subsequent periods reflect the percentage of the original cohort that made at least one additional purchase in that month offset.
get_repeat_purchase_rate()
Ratio of customers who made more than one transaction in the period.
Returns:
{
"total_customers": 890,
"repeat_customers": 312,
"repeat_purchase_rate": 35.06
}
get_rfm_scores()
Rank-based quintile scoring (1–5) across recency, frequency, and monetary dimensions per customer. Store-isolated. Higher scores are better across all three dimensions.
Returns: list of per-customer score rows
[
{
"customer_id": "uuid",
"recency_score": 5,
"frequency_score": 3,
"monetary_score": 4,
"rfm_total": 12
}
]
ProcurementAnalyticsService
Location: api/nextango/apps/procurement/analytics_service.py (delegated via analytics domain)
get_supplier_lead_time_variance()
Actual vs expected lead time per supplier across purchase orders for the period.
Returns: list of per-supplier aggregates
[
{
"supplier_id": "uuid",
"supplier_name": "Acme Co.",
"avg_actual_lead_days": 8.4,
"avg_expected_lead_days": 7.0,
"variance_days": 1.4,
"order_count": 12
}
]
PromotionAnalyticsService — campaign lift
Location: api/nextango/apps/promotions/analytics_service.py (delegated via analytics domain)
get_campaign_lift(campaign_id)
Compares promo-code revenue during a campaign's test window against an equal-duration control window immediately preceding it.
Returns:
{
"test_revenue": "12480.00",
"control_revenue": "9310.00",
"test_order_count": 248,
"control_order_count": 194,
"lift_pct": 34.05
}
A positive lift_pct indicates the campaign period outperformed the equivalent prior window. lift_pct is null when control_revenue is zero.