# Elasticsearch Services Reference (customer_subscription_v1)

This file is the canonical ES reference for current code.

## Core runtime services
- `app/Services/Elasticsearch/DashboardElasticsearchService.php`
  - central ES client + query execution
  - index resolution (`config('elasticsearch.index')`)
  - compatibility rewrite hook for object-mapped legacy indexes
- `app/Services/Elasticsearch/BaseElasticsearchQueryService.php`
  - shared root/nested query builders and helpers for module services

## Module service map (with public methods)

### Dashboard page
File: `app/Services/Elasticsearch/DashboardPageElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchRegistrationCount(...)`
- `fetchConversionCount(...)`
- `fetchActiveAnytimeCount(...)`
- `fetchActiveSubscribersAtDate(...)`
- `fetchChurnedCount(...)`
- `fetchPaymentHealth(...)`
- `fetchPaymentTrends(...)`
- `fetchPaymentGatewayDistribution(...)`
- `fetchPaymentFailures(...)`
- `fetchChurnedCustomers(...)`
- `fetchTopSubscriptionPackageTitles(...)`
- `fetchSubscriptionSeriesByPackageTitle(...)`
- `fetchDateHistogramCardinality(...)`
- `dateHistogramCardinality(...)`

### Billing
File: `app/Services/Elasticsearch/BillingElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchBillingPaymentGateways(...)`
- `fetchBillingKpis(...)`
- `fetchBillingPaymentSeries(...)`
- `fetchBillingGatewayDistribution(...)`
- `fetchBillingProviderHealth(...)`
- `searchBillingInvoices(...)`
- `aggregateBillingGateways(...)`
- `aggregateBillingSubscriptions(...)`

### Business Analytics
File: `app/Services/Elasticsearch/BusinessAnalyticsElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchBusinessAnalyticsMrrArr(...)`
- `fetchBusinessAnalyticsRevenueAndActivations(...)`
- `fetchBusinessAnalyticsChurnRate(...)`
- `fetchBusinessAnalyticsRevenueByPackage(...)`
- `fetchBusinessAnalyticsAverageLtv(...)`
- `fetchBusinessAnalyticsMonthlyChurnRates(...)`

### Business Units
File: `app/Services/Elasticsearch/BusinessUnitsElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchBusinessUnitsCurrencyStats(...)`

### Campaign Segment
File: `app/Services/Elasticsearch/CampaignSegmentElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchSegmentData(...)`

### Global Search
File: `app/Services/Elasticsearch/GlobalSearchElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `searchTransactions(...)`

### Product Admin
File: `app/Services/Elasticsearch/ProductAdminElasticsearchService.php`
- `fetchTopPackagesPerformance(...)`

### Reports
File: `app/Services/Elasticsearch/ReportsElasticsearchService.php`
- `isEnabled()`
- `isConfigured()`
- `fetchRows(...)`

### Subscriber360
File: `app/Services/Elasticsearch/Subscriber360ElasticsearchService.php`
- `query(...)`
- `fetchCustomerDocument(...)`
- `fetchCards(...)`
- `countDistinctUsers(...)`
- `searchCustomerTable(...)`
- `fetchUserGrowthBuckets(...)`
- `fetchEngagementBuckets(...)`
- `fetchSignupVsSuspendedCounts(...)`
- `fetchHeatmapBuckets(...)`

### BackOffice coupon analytics
File: `app/Services/Elasticsearch/BackOfficeCouponAnalyticsElasticsearchService.php`
- `fetchCouponAnalytics(...)`

## Primary route groups consuming ES services
- `/admin/api/dashboard/widgets/*`
- `/admin/api/billing/*`
- `/admin/business-analytics/widgets/*`
- `/admin/business-units/widgets/data`
- `/campaign-segment`
- `/global-search-data`
- `/admin/api/back-office/coupons/analytics/*`
- `/admin/api/reports/{reportKey}` and `/admin/api/reports/{reportKey}/export`
- `/admin/subscriber-360/widgets/*`
- `/admin/api/products-packages/dashboard-detail`

## Mapping assumptions used by services
- Index: `customer_subscription_v1`
- Root fields include: `app_id`, `sms_cust_id`, `created_at`, `email_id`, `phone_number`
- Nested path: `orders`
- Optional nested sub-path: `orders.subscription`
- Services intentionally use combined logic where needed:
  - `orders.order_status` and/or `orders.subscription.subscription_status`
  - `orders.order_created_at` and/or `orders.subscription.subscription_created_at`

## Fallback behavior
- SQL fallback/availability decisions are backend service-driven (via `DashboardElasticsearchService` + module service consumers).
- Keep fallback logic out of blades.
- Timeline active-series validation now prefers ES continuity and avoids expensive SQL timeline fallback for long-range queries.

## ES profiling logs (dashboard)
- Runtime query profiling is centralized in `DashboardElasticsearchService::query(...)`.
- Log keys:
  - `dashboard.es_query`
  - `dashboard.es_query_slow`
  - `dashboard.es_query_failed`
- Payload includes:
  - caller method (e.g. `DashboardPageElasticsearchService::fetchPaymentTrends`)
  - `timings_ms.wall`, `timings_ms.es_took`
  - extracted filters (`app_id`, date ranges, package/currency/gateway, statuses)
  - `query_hash`, `request_path`
- Slow threshold can be tuned via `DASHBOARD_ES_SLOW_MS`.

## Query execution defaults (dashboard ES runtime)
- In `DashboardElasticsearchService::query(...)`, aggregation-only requests (`size: 0` + `aggs`) are executed with `track_total_hits: false` unless explicitly provided.
- In `DashboardPageElasticsearchService::fetchPaymentTrends(...)` and `fetchPaymentTrendsObjectAccurate(...)`, histogram interval is adaptive for large date ranges:
  - `day` for `<= 90` days
  - `week` for `91..730` days
  - `month` for `> 730` days
