Files
telecom-platform/apps/carrier-connector/tests/e2e/subscriber_journey_test.go
T
NutcaseandGitHub 88909d0627 New features (#67)
* refactor: Rename handler package to handlers in carrier-connector

- Rename internal/handler directory to internal/handlers
- Update handler import path in main.go and routes.go

* feat: Add SM-DP+ handler with multi-carrier management and profile operations

- Add SMDPHandler struct with manager field and NewSMDPHandler constructor
- Add AddCarrier endpoint with JSON binding and carrier configuration support
- Add RemoveCarrier endpoint with carrier ID parameter validation
- Add DownloadProfile endpoint with 30-second timeout and context cancellation
- Add GetCarrierStatus endpoint returning all carriers with timestamp
- Add GetProfileStatus endpoint with EID/ICCID validation

* feat: Add SM-DP+ integration layer with multi-carrier system initialization and route registration

- Add SMDPIntegration struct with service, handler, repository, and logger fields
- Add NewSMDPIntegration constructor with default carrier initialization
- Add InitializeSystem method with carrier health logging and status tracking
- Add RegisterRoutes method with profile, carrier, health, and metrics endpoints
- Add healthHandler with carrier health status aggregation and degraded state detection
- Add metricsHandler

* feat: Add SM-DP+ service layer with multi-carrier management and profile download operations

- Add SMDPService struct with manager, repository, and logger fields
- Add NewSMDPService constructor with default config and background health checking
- Add InitializeDefaultCarriers with AT&T, Verizon, and T-Mobile DE configurations
- Add DownloadProfile method with context support and request logging
- Add GetOptimalCarrier wrapping SelectCarrier for best carrier selection
- Add GetCarrierHealth returning

* feat: Add SM-DP+ manager with multi-carrier load balancing, health checking, and profile operations

- Add DefaultManagerConfig with 30s health checks, 3 retries, and circuit breaker configuration
- Add CarrierConfig struct with ES2 settings, MCC/MNC, priority, and feature support
- Add ToCarrier method converting CarrierConfig to Carrier with metrics and capabilities
- Add HealthChecker with periodic carrier health monitoring and status evaluation
- Add LoadBalancer with weighted round-robin, least

* feat: Add intelligent carrier selection service with scoring, recommendations, and analytics

- Add SelectionService struct with manager, handler, and logger fields
- Add NewSelectionService constructor with info-level logging
- Add IntelligentCarrierSelection method with comprehensive criteria evaluation
- Add IntelligentSelectionRequest with region, profile type, urgency, and cost sensitivity
- Add UserPreferences and BusinessContext structs for selection customization
- Add IntelligentSelectionResponse with selected

* feat: Add carrier selection handler with optimal selection, analytics, and performance monitoring endpoints

- Add SelectionHandler struct with manager and logger fields
- Add NewSelectionHandler constructor with info-level logging
- Add SelectOptimalCarrier endpoint with criteria validation and scoring
- Add SelectCarrier endpoint using default selection criteria
- Add GetSelectionHistory endpoint with carrier ID path parameter
- Add UpdateLearning endpoint with performance feedback validation
- Add GetSelectionAnalytics endpoint with carrier stats

* feat: Add carrier selection integration layer with multi-carrier setup, HTTP server, and demo capabilities

- Add SelectionIntegration struct with manager, selection service, handler, and SMDP service fields
- Add NewSelectionIntegration constructor with default manager config and 30s health checks
- Add SetupCarriers with AT&T, Verizon, T-Mobile DE, and Orange FR configurations
- Add StartServer method with health endpoint and 30s read/write timeouts
- Add StartHealthChecking wrapper for background

* feat: Refactor profile handlers into modular core components with simplified operations

- Split profile_handlers.go into profile_handlers_core.go, profile_handlers_management_core.go, and profile_handlers_management_delete.go
- Simplify OrderProfileHandlerWithRepo with ICCID/IMSI-only validation and "downloaded" state
- Remove webhook and message queue notifications from order handler
- Add UpdateProfileHandler with state validation for downloaded/activated/deactivated/expired
- Add DeleteProfileHandler with existence

* refactor: Extract carrier setup logic into separate file and remove unnecessary comments

- Move SetupCarriers method from selection_integration.go to new setup_carriers.go file
- Remove redundant comments from SelectionIntegration struct and methods
- Clean up inline comments in RunDemo method while preserving functionality

* feat: Add intelligent carrier selection algorithm with machine learning optimization and performance tracking

- Add SelectionAlgorithm with scoring, weighting, and ML-based carrier selection
- Add SelectionCriteria struct with region, profile type, urgency, and cost/performance weights
- Add CarrierScore with performance, reliability, cost, region, and capability scores
- Add calculateWeightedScore combining all scores with ML-optimized weights
- Add getWeights with urgency-based adjustments

* feat: Integrate SelectionAlgorithm into SMDPManager with optimal carrier selection and learning capabilities

- Add selector field to SMDPManager struct with SelectionAlgorithm type
- Initialize selector in NewSMDPManager constructor
- Add SelectOptimalCarrier method filtering healthy carriers and delegating to selection algorithm
- Add SelectCarrier wrapper with default criteria (operational profile, medium urgency, balanced weights)
- Add GetSelectionHistory method returning carrier selection history
- Add UpdateLearning

* refactor: Simplify profile handler function names by removing WithRepo suffix

- Rename ListProfilesHandlerWithRepo to ListProfilesHandler
- Rename GetProfileHandlerWithRepo to GetProfileHandler
- Rename DeleteProfileHandlerWithRepo to DeleteProfileHandler

* feat: Add pricing engine with rate plan validation, cost calculation, and price optimization

- Add PricingEngine struct with repository and logger fields
- Add ValidateRatePlan with comprehensive validation for fields, dates, allowances, overage rates, discounts, and early termination
- Add CalculateOptimalPrice with market analysis and recommended pricing based on competitor data
- Add ValidateSubscription with plan availability, validity dates, and discount validation
- Add CalculateSubscriptionCost with base

* feat: Add rate plan analytics handlers with usage, revenue, popularity, and dashboard endpoints

- Add AnalyticsResponse struct with success, message, and data fields
- Add GetUsageAnalytics with date range parsing, default last month period, and group by support
- Add GetRevenueAnalytics with RFC3339 date parsing and configurable filters
- Add GetPopularPlans with configurable limit defaulting to 10
- Add GetDashboardData aggregating top 5 popular plans, 30-day usage analytics, and revenue analytics

* feat: Add rate plan handler layer with CRUD operations, management endpoints, and analytics support

- Add RatePlanHandler struct with service and logger fields
- Add CreateRatePlan with JSON binding, draft status initialization, and comprehensive field mapping
- Add GetRatePlan with ID path parameter extraction and not found handling
- Add UpdateRatePlan with selective field updates and existing plan retrieval
- Add DeleteRatePlan with active subscription conflict detection
- Add ListRatePlans with carrier

* feat: Add rate plan type system with comprehensive domain models, allowances, subscriptions, and analytics support

- Add RatePlan struct with carrier, region, pricing, allowances, features, discounts, and validity fields
- Add PlanType enum with prepaid, postpaid, hybrid, pay-as-you-go, and unlimited options
- Add PlanStatus enum with draft, active, inactive, archived, and suspended states
- Add BillingCycle enum with daily, weekly, monthly, quarterly, and yearly options
- Add DataAllowance, VoiceAllowance, and

* feat: Add rate plan service layer with CRUD operations, subscription management, usage tracking, and analytics support

- Add Service struct with repository and logger fields
- Add CreateRatePlan with ID generation, validation, and comprehensive field checks
- Add GetRatePlan, UpdateRatePlan, and DeleteRatePlan with active subscription conflict detection
- Add ListRatePlans and SearchRatePlans with filtering and sorting support
- Add SubscribeToPlan with plan availability validation, duplicate subscription

* feat: Add carrier integration layer with optimal carrier selection, rate plan recommendations, and analytics support

- Add CarrierSelectionIntegrator struct with rate plan repository, SMDP manager, and logger fields
- Add GetOptimalCarrierWithRatePlan with region filtering, carrier grouping, performance scoring, and combined evaluation
- Add RecommendRatePlansForCarrier with carrier validation, active plan filtering, and recommendation creation
- Add UpdateCarrierSelectionCriteria with 30-day usage analytics

* feat: Add rate plan repository interface with GORM models and extended types for carrier integration

- Add Repository interface with rate plan CRUD, subscription management, usage tracking, and analytics operations
- Add GORM table name methods for RatePlan, RatePlanSubscription, and RatePlanUsage models
- Add GORM hooks with automatic timestamp handling for BeforeCreate and BeforeUpdate operations
- Add SearchCriteria with carrier, region, plan type, price range, pagination, and sorting fields

* feat: Refactor pricing engine by extracting calculation methods into separate file

- Move calculateDataOverage, calculateVoiceOverage, calculateSMSOverage, calculateDiscounts, and calculateRecommendedPrice to price_calculation.go
- Remove validation helper methods from pricing_engine.go
- Remove PriceOptimization and CostBreakdown type definitions
- Update Logger interface to use `any` instead of `interface{}`
- Remove inline comments throughout pricing_engine.go
- Add switch statement for discount type handling in calculateDiscounts

* refactor: Extract core rate plan types into separate file

- Move RatePlan struct from types.go to types_core.go
- Move PlanType enum with prepaid, postpaid, hybrid, pay-as-you-go, and unlimited options to types_core.go
- Move PlanStatus enum with draft, active, inactive, and archived states to types_core.go
- Move BillingCycle enum with daily, weekly, monthly, quarterly, and yearly options to types_core.go
- Add documentation comments for PlanType, PlanStatus, and BillingCycle enums
- Remove PlanStatusSuspended from PlanStatus enum

* feat: Add GORM repository implementation with CRUD operations, subscription management, usage tracking, and analytics support

- Add GormRepository struct with database and logger fields
- Add CreateRatePlan, GetRatePlan, UpdateRatePlan, and DeleteRatePlan with automatic timestamp handling
- Add ListRatePlans with carrier, region, plan type, status, price range, and validity filtering
- Add CountRatePlans with comprehensive filter support
- Add CreateSubscription, GetSubscription, UpdateSubscription, and DeleteSubscription with timestamp

* feat: Add carrier configuration layer with GORM repository, file loading, and model conversion support

- Add GormCarrierRepository struct with database and logger fields
- Add CarrierModel with ID, name, MCC, MNC, country code, active status, priority, ES2 config, capabilities, and timestamp fields
- Add GetCarriers with active carrier filtering and model-to-carrier conversion
- Add GetCarrier with ID lookup and not found handling
- Add SaveCarrier with upsert logic for create or update operations

* feat: Add carrier configuration file loading with JSON-based carrier setup and validation

- Add carriers.json with AT&T US, Verizon US, T-Mobile Germany, Orange France, and Vodafone UK configurations
- Add LoadCarriersFromFile with JSON parsing and config file reading
- Add ConvertConfigToCarriers with model-to-carrier conversion logic
- Add validateCarrier with ID, name, MCC, MNC, country code, and ES2 config validation
- Replace hardcoded carrier setup with file-based configuration loading
- Add success

* refactor: Extract service methods into separate files for better organization

- Move GetUsage, GetUsageHistory, GetUsageAnalytics, GetRevenueAnalytics, and GetPopularPlans to service_analytics.go
- Move validateRatePlan, validateSubscribeRequest, calculateNextBillingDate, and calculateCycleEnd to service_methods.go
- Move SubscribeToPlan, GetSubscription, UpdateSubscription, CancelSubscription, GetActiveSubscription, and ListSubscriptions to service_subscriptions.go
- Move RecordUsage to service_usage.go

* feat: Add currency configuration file with 20 major currencies and regional support

- Add currencies.json with USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, INR, BRL, MXN, SEK, NOK, DKK, SGD, HKD, NZD, ZAR, KRW, and TRY configurations
- Add currency metadata with code, name, symbol, decimal places, active status, and supported regions
- Add regional mappings for currency support across multiple countries and territories

* feat: Add currency analytics service with revenue tracking, transaction analysis, and usage statistics

- Add AnalyticsServiceImpl struct with repository and logger fields
- Add GetRevenueByCurrency with completed transaction filtering and revenue aggregation by currency
- Add GetTransactionVolumeByCurrency with transaction count grouping
- Add GetExchangeRateTrends with historical rate retrieval and date-based filtering
- Add GetCurrencyUsageStats with total/active currency counts, transaction volume

* feat: Add multi-currency billing service with transaction processing, currency conversion, and history tracking

- Add BillingServiceImpl struct with repository, exchange service, logger, and base currency fields
- Add NewBillingService constructor with dependency injection
- Add ProcessBilling with request validation, currency conversion, transaction creation, and payment processing
- Add ConvertAmount wrapper delegating to exchange service
- Add GetBillingHistory with profile ID filtering and transaction retries

* feat: Add exchange rate service with multi-provider support, currency conversion, and historical rate tracking

- Add ExchangeRateService struct with repository, logger, providers, and base currency fields
- Add NewExchangeRateService constructor and AddProvider for provider registration
- Add GetExchangeRate with repository caching, provider fallback, and same-currency handling
- Add ConvertAmount wrapper with exchange rate retrieval and amount calculation
- Add RefreshRates with multi-provider rate

* refactor: Extract currency interfaces and GORM models into separate files

- Move Repository, ExchangeRateProvider, BillingService, and AnalyticsService interfaces from types.go to new interface.go
- Move BillingSummary and CurrencyUsageStats structs to interface.go
- Move CurrencyModel, ExchangeRateModel, and TransactionModel to new models.go
- Move GORM hooks (BeforeCreate, BeforeUpdate) and TableName methods to models.go
- Remove redundant comments from exchange_rate_service.go

* feat: Add rate plan currency integrator with subscription creation, cost calculation, and multi-currency billing support

- Add RatePlanCurrencyIntegrator struct with billing service, exchange service, rate plan service, logger, and base currency fields
- Add NewRatePlanCurrencyIntegrator constructor with dependency injection
- Add SubscribeToPlanWithCurrency with price conversion, subscription creation, and initial billing processing
- Add CalculatePlanCostInCurrency with base cost calculation

* feat: Add currency repository with GORM implementation, rate plan integration, and transaction management

- Add GormRepository with CRUD operations for currencies, exchange rates, and transactions
- Add repository helper methods for model-to-domain conversions with JSON metadata handling
- Add GetHistoricalRates with date range filtering and chronological ordering
- Add ListExchangeRates with currency pair, active status, and date range filtering
- Add CreateTransaction, GetTransaction, UpdateTransaction, and List

* feat: Add currency handler layer with conversion, billing, exchange rates, and analytics endpoints

- Add CurrencyHandler struct with billing service, exchange service, and logger fields
- Add ConvertCurrency endpoint with JSON binding and amount conversion support
- Add GetExchangeRate endpoint with currency pair path parameters
- Add ProcessBilling endpoint with billing request validation and transaction processing
- Add GetBillingHistory with profile ID filtering, date range, limit, and offset support

* refactor: Rename service package to services and move repository implementations to repository package

- Rename internal/service to internal/services in carrier-connector
- Update service imports in selection_integration.go and smdp_integration.go
- Move currency repository files from internal/currency to internal/repository
- Move rate plan repository files from internal/rateplan to internal/repository
- Update package declarations and imports for currency domain types
- Add currency package imports

* refactor: Add ExchangeRateService interface and format currency types with consistent alignment

- Add ExchangeRateService interface with GetExchangeRate, ConvertAmount, GetRateHistory, UpdateExchangeRate, GetSupportedCurrencies, ValidateCurrencyPair, and RefreshRates methods
- Add CurrencyRevenue struct with currency and revenue fields
- Add TransactionTypeStats struct with type, count, amount, and currency fields
- Align struct field tags consistently across Currency, ExchangeRate, Transaction, and request/response types

* refactor: Update service layer to use repository package types and align imports

- Update Service struct to use repository.Repository interface
- Update all method signatures to use repository package types (RatePlan, RatePlanSubscription, RatePlanUsage, etc.)
- Update filter and request types to use repository package (RatePlanFilter, SubscriptionFilter, CalculateCostRequest, etc.)
- Update status constants to use repository package (SubscriptionStatusActive, PlanStatusActive, DiscountTypePercentage, DiscountTypeFixed)

* refactor: Update handler constructors to use interface types instead of concrete implementations

- Update CurrencyHandler.exchangeService field from *currency.ExchangeRateService to currency.ExchangeRateService interface
- Update NewCurrencyHandler parameter from *currency.ExchangeRateService to currency.ExchangeRateService interface
- Update RatePlanHandler.service field from *rateplan.Service to rateplan.Service interface
- Update NewRatePlanHandler parameter from *rateplan.Service to rateplan.Service interface

* refactor: Rename currency parameter from 'currency' to 'curr' in currencyToModel helper method and add Service interface to rate plan package

- Rename currency parameter to curr in GormRepository.currencyToModel to avoid shadowing currency package name
- Add Service interface with rate plan, subscription, usage, and analytics operations
- Add CreateRatePlan, GetRatePlan, UpdateRatePlan, DeleteRatePlan, ListRatePlans, and SearchRatePlans methods
- Add SubscribeToPlan, GetSubscription, UpdateSubscription, CancelSubscription, GetActiveSubscription, and ListSubscriptions methods
- Add Rec

* feat: Add repository types package with rate plan, subscription, usage, and analytics domain models

- Add Repository interface with rate plan CRUD, subscription management, usage tracking, and analytics operations
- Add RatePlan struct with pricing, allowances, overage rates, discounts, and metadata fields
- Add RatePlanSubscription struct with billing cycle, auto-renewal, and applied discounts support
- Add RatePlanUsage struct with cycle tracking and data/voice/SMS usage metrics
- Add filter types for rate plans, subscriptions, usage analytics, and revenue analytics

* feat: Add tenant handler layer with CRUD, user management, API keys, and analytics endpoints

- Add TenantHandler struct with tenant service and logger fields
- Add CreateTenant, GetTenant, GetTenantByDomain, UpdateTenant, DeleteTenant, and ListTenants endpoints
- Add AddUserToTenant, GetTenantUser, UpdateTenantUser, RemoveUserFromTenant, and ListTenantUsers endpoints
- Add CreateAPIKey, GetAPIKey, UpdateAPIKey, DeleteAPIKey, and ListAPIKeys endpoints with key string return on creation

* feat: Add tenant analytics service with dashboard, usage, performance, cost analytics, and comprehensive reporting

- Add TenantAnalyticsService struct with repository, metrics collector, event publisher, and logger fields
- Add GetTenantDashboard with usage stats, metrics, recent events, and quota status aggregation
- Add GetTenantMetrics with active users, request tracking, error rate calculation, response time analysis, and health score computation
- Add GetUsageAnalytics with time range filtering, resource type breakdown

* feat: Add tenant types package with filters, requests, usage stats, events, and metrics domain models

- Add TenantFilter with ID, name, domain, status, plan, pagination, and sorting fields
- Add CreateTenantRequest, UpdateTenantRequest with plan, limits, settings, and metadata support
- Add TenantUserFilter, CreateTenantUserRequest, UpdateTenantUserRequest with role and status management
- Add CreateAPIKeyRequest, UpdateAPIKeyRequest with permissions, rate limits, and expiration support
- Add TenantUs

* feat: Add tenant integration layer with repository wrapper, service manager, quota checker, and event logger

- Add TenantAwareCurrencyRepository wrapper with tenant isolation for all currency repository methods
- Add NewTenantAwareCurrencyRepository and WithTenant methods for tenant context management
- Add TenantIntegrationManager with GetTenantAwareServices for tenant validation and configuration
- Add TenantAwareServices struct with tenant context, config, and currency service fields
- Add TenantResourceQuotaChecker

* feat: Add tenant package interfaces with repository, service, middleware, and supporting components

- Add Repository interface with tenant CRUD, user management, API keys, usage tracking, config, and event operations
- Add Service interface with tenant management, user operations, API key handling, quota checking, config management, authentication, and analytics methods
- Add Middleware interface with request extraction, access validation, context injection, rate limiting, and resource isolation

* feat: Add tenant middleware with authentication, authorization, isolation, and activity logging

- Add TenantMiddleware struct with tenant service and logger fields
- Add ExtractTenantFromHeader and ExtractTenantFromAPIKey methods for tenant identification from headers, subdomains, and API keys
- Add RequireTenant middleware with header and API key extraction fallback and tenant access validation
- Add RequireTenantRole middleware with role-based access control for multiple required roles

* feat: Add tenant domain models with multi-tenancy support, user management, usage tracking, and API key authentication

- Add Tenant struct with plan, limits, settings, and metadata fields
- Add TenantStatus constants (active, inactive, suspended, deleted)
- Add TenantPlan constants (free, basic, pro, enterprise)
- Add TenantSettings with currency, feature flags, rate limiting, security, and compliance configuration
- Add PasswordPolicy struct with length, character requirements, and age settings

* feat: Add tenant repository implementation with GORM-based data access layer for multi-tenancy support

- Add GormTenantRepository struct with GORM database field
- Add CreateTenant, GetTenant, GetTenantByDomain, UpdateTenant, DeleteTenant methods with context support
- Add ListTenants and CountTenants with filtering by ID, name, domain, status, plan, sorting, and pagination
- Add CreateTenantUser, GetTenantUser, UpdateTenantUser, DeleteTenantUser methods for user management
- Add ListTenantUsers and

* feat: Add tenant service extended methods with quota management, usage tracking, permissions, and metrics collection

- Add CheckQuota method with quota limit validation, unlimited quota support (-1), and quota exceeded event logging
- Add GetUsageStats with resource breakdown, quota status calculation, warning/critical thresholds, and active user counting
- Add UpdateUsage with automatic usage record creation and existing record updates
- Add GetQuotaStatus, GetTenantConfig, UpdateTenantConfig, Get

* feat: Add tenant service implementation with CRUD operations, user management, API key handling, and event logging

- Add ServiceImpl struct with repository, rate limiter, event publisher, config manager, audit logger, metrics collector, and logger fields
- Add CreateTenant with validation, domain uniqueness check, default settings/quotas/features initialization, and tenant created event
- Add GetTenant, GetTenantByDomain, UpdateTenant, DeleteTenant, and ListTenants methods with event logging

* feat: Add tenant-aware repository layer with isolation, validation, query building, and resource access control

- Add TenantAwareRepository with GORM database and tenant ID fields
- Add NewTenantAwareRepository, WithTenant, GetTenantID, ValidateTenant methods for tenant context management
- Add TenantScopedQuery and TenantScopedTransaction for tenant-isolated database operations
- Add CreateWithTenant, GetByTenantID, UpdateWithTenant, DeleteWithTenant, ListWithTenant, CountWithTenant helper methods
- Add TenantA

* refactor: Move tenant repository files to repository package and update imports

- Move tenant_aware_repository.go from internal/tenant to internal/repository package
- Move repository.go to tenant_repository.go in internal/repository package
- Add tenant package import for type references in tenant_repository.go
- Update filter type references to use tenant package prefix (TenantFilter, TenantUserFilter, TenantUsageFilter)
- Update return type for GetUsageStats to use tenant.TenantUsageStats

* feat: Add tenant integration layer with repository wrapper, analytics types, and performance monitoring

- Add TenantAwareCurrencyRepository wrapper with tenant isolation for all currency repository methods
- Add NewTenantAwareCurrencyRepository and WithTenant methods for tenant context management
- Add TenantIntegrationManager with GetTenantAwareServices for tenant validation and configuration
- Add TenantAwareServices struct with tenant context, config, and currency service fields
- Add TenantResource

* feat: Add currency analytics, billing, and exchange rate services with multi-currency support and transaction processing

- Add AnalyticsServiceImpl with revenue/volume analysis, exchange rate trends, usage stats, and transaction type analytics
- Add GetRevenueByCurrency, GetTransactionVolumeByCurrency, GetExchangeRateTrends, GetCurrencyUsageStats methods
- Add GetMonthlyRevenueTrends, GetTopCurrenciesByRevenue, GetTransactionTypeAnalytics for reporting
- Add BillingServiceImpl with multi-currency billing, payment

* refactor: Update tenant integration to use concrete service types and tenant package imports

- Change TenantIntegrationManager.tenantService from Service interface to *services.TenantServiceImpl concrete type
- Change TenantResourceQuotaChecker.tenantService from Service interface to *services.TenantServiceImpl
- Change TenantEventLogger.tenantService from Service interface to *services.TenantServiceImpl
- Update TenantAwareServices fields to use tenant package types (TenantContext, TenantConfig)

* feat: Add TenantRepository interface with CRUD operations, user management, API keys, usage tracking, and event logging

- Add TenantRepository interface with CreateTenant, GetTenant, GetTenantByDomain, UpdateTenant, DeleteTenant, ListTenants, CountTenants methods
- Add CreateTenantUser, GetTenantUser, UpdateTenantUser, DeleteTenantUser, ListTenantUsers, CountTenantUsers for user management
- Add CreateAPIKey, GetAPIKey, GetAPIKeyByHash, UpdateAPIKey, DeleteAPIKey, ListAPIKeys for API key operations

* refactor: Extract ES2 types from client.go to separate types.go file

- Move ES2Client struct definition from client.go to types.go
- Move DownloadProfileRequest, DownloadProfileResponse, GetProfileStatusRequest, GetProfileStatusResponse types to types.go
- Move DeleteProfileRequest, DeleteProfileResponse, EnableProfileRequest, EnableProfileResponse types to types.go
- Move DisableProfileRequest, DisableProfileResponse types to types.go
- Add net/http, time, and config package imports to types.go

* refactor: Move tenant repository implementation to tenant package and update imports

- Move GormTenantRepository implementation from repository package to tenant package
- Move TenantResourceValidator from repository to tenant package
- Update tenant_aware_repository.go to import tenant package for Tenant and TenantStatusActive types
- Remove duplicate tenant model definitions and helper methods from repository package
- Update ValidateTenant to use tenant.Tenant and tenant.TenantStatusActive types

* refactor: Refactor tenant and rate plan services with improved code organization and currency integration updates

- Update RatePlanCurrencyIntegrator to use billingService.ConvertAmount with CurrencyConversionRequest struct instead of exchangeService
- Remove calculateOverageCost method from rateplan_methods.go (moved or deprecated)
- Rename tenant variable to newTenant in CreateTenant to avoid shadowing
- Extract tenant user methods from tenant_user.go to new tenant_user_methods.go file

* refactor: Add rate plan currency integration service and update tenant repository with user count method

- Add RatePlanCurrencyIntegrator with SubscribeToPlanWithCurrency, CalculatePlanCostInCurrency, calculateOverageCost methods
- Add NewRatePlanCurrencyIntegrator constructor with billingService, exchangeService, ratePlanService, logger, baseCurrency fields
- Add currency conversion support for rate plan subscriptions with exchange rate metadata tracking
- Add billing integration for initial subscription

* refactor: Replace map[string]interface{} with map[string]any across currency, handlers, integration, and rateplan packages

- Update BillingSummary.Breakdown field type from map[string]interface{} to map[string]any
- Update Transaction.Metadata field type from map[string]interface{} to map[string]any
- Update RatePlanCurrencyIntegrator subscription and billing metadata to use map[string]any
- Update handler request/response types to use map[string]any (CreateRatePlanRequest, UpdateRatePlanRequest,

* refactor: Implement tenant analytics dashboard and usage analytics with helper methods

- Implement GetTenantDashboard with usage stats, metrics, recent events, and quota status
- Implement GetUsageAnalytics with usage by type, trends, and peaks
- Implement GetPerformanceAnalytics with API performance, resource performance, errors, and slow queries
- Extract helper methods to tenant_analytics_mock.go: parseTimeRange, parseAPIRequestEvent, parseErrorEvent, parseSlowQueryEvent, calculateAPIPerformance, build

* refactor: Remove unused rate plan currency integrator and tenant analytics mock helper methods

- Delete RatePlanCurrencyIntegrator implementation from rateplan_core.go
- Delete SubscribeToPlanWithCurrency, CalculatePlanCostInCurrency, calculateOverageCost methods
- Delete tenant analytics mock helper methods from tenant_analytics_mock.go
- Remove getMockResourceCount, getMockQuotaLimit, getMockQuotaUsed, parseTimeRange methods
- Remove parseAPIRequestEvent, parseErrorEvent, parseSlowQueryEvent, calculateAPI

* feat: Add pricing handlers with CRUD operations, rule application, price calculation, and analytics endpoints

- Add PricingHandler with CreateRule, GetRule, UpdateRule, DeleteRule, ListRules methods
- Add CalculatePrice endpoint for price calculation based on active rules
- Add ApplyRules endpoint for applying specific pricing rules to context
- Add GetAnalytics endpoint for retrieving pricing analytics by tenant
- Add RegisterRoutes method to register pricing routes under /pricing group

* feat: Add Snowflake ID generator with thread-safe generation, parsing utilities, and default generator

- Add Snowflake struct with mutex, timestamp, nodeID, sequence fields
- Add NewSnowflake constructor with nodeID validation (0 to MaxNodeID range)
- Add Generate method with sequence overflow handling and millisecond-based timestamp
- Add GenerateString method for string representation of generated IDs
- Add Parse, Time, NodeID, Sequence utility functions for ID decomposition
- Add defaultGenerator

* refactor: Extract tenant integration helper types to separate file and replace ID generation with id package

- Move TenantAwareServices, TenantResourceQuotaChecker, TenantEventLogger from tenant_integration.go to tenant_integration_core.go
- Move wrapCurrencyService, NewTenantResourceQuotaChecker, NewTenantEventLogger, CheckQuota, UpdateUsage methods to tenant_integration_core.go
- Move LogResourceAccess, LogQuotaViolation methods to tenant_integration_core.go
- Replace generateID helper with id.

* feat: Add pricing interfaces and types for dynamic pricing rule management

- Add Repository interface with CreateRule, GetRule, UpdateRule, DeleteRule, ListRules, CountRules methods
- Add GetActiveRules, GetRulesByType methods for rule evaluation
- Add Service interface with rule management, pricing calculations, validation, and analytics methods
- Add RuleEngine interface with EvaluateRule, ApplyRule, ValidateConditions, ExecuteActions methods
- Add PricingEventHandler interface for rule lifecycle events
- Add PricingValidator interface for rule and context validation
- Add PricingCache interface for caching pricing data

* refactor: Refactor tenant analytics to use repository data and extract helper methods to separate files

- Move parseAPIRequestEvents, buildResourcePerformance, parseErrorEvents, parseSlowQueryEvents from tenant_analytics_mock.go to tenant_analytics.go
- Update buildUsageByType to fetch usage statistics from repository instead of using mock data
- Add calculateResourceUsageAnalytics helper to calculate analytics from usage records
- Update buildUsageTrends to use repository data with buildUsageTrendData helper
- Update buildUsagePeaks to use repository data with buildUsagePeakData helper

* feat: Add pricing repository, tenant-aware transaction support, and pricing integration service

- Add GormPricingRepository with CreateRule, GetRule, UpdateRule, DeleteRule, ListRules, CountRules methods
- Add GetActiveRules, GetRulesByType methods for retrieving active pricing rules by tenant and type
- Add TenantScopedDB wrapper with automatic tenant filtering for tenant-aware database operations
- Implement TenantScopedTransaction with tenant context propagation and automatic filtering

* refactor: Extract helper methods, fix formatting, and add TODO comments for pending implementations

- Extract generateHistoryAnalytics helper in selection_handler_methods.go
- Extract generateRecommendations helper in selection_handler_selection.go
- Extract parsePositiveInt helper in rateplan_handlers_analytics.go
- Replace hardcoded URL path with action parameter in ES2Service.sendActivationRequest
- Add TODO comments for wrapCurrencyService and updateCarrierWeights pending implementations
- Fix struct field alignment and formatting in carrier_methods.go

* refactor: Replace time and ID generation helpers with centralized id package utilities

- Replace getCurrentTime() calls with id.GetCurrentTime() in pricing_integration.go and pricing_service.go
- Replace generateRuleID() with id.GenerateRuleID() in pricing rule creation
- Replace generateEventID() with id.GenerateEventID() in tenant middleware
- Remove local helper functions: generateRuleID, getCurrentTime, generateEventID, generateRandomString, getCurrentTimestamp
- Remove unused time package imports

* feat: Add ID generation utilities with rule ID, event ID, and random string generators

- Add GenerateRuleID function using nanosecond timestamp
- Add GetCurrentTime helper returning current time
- Add GenerateEventID function with "evt_" prefix and 16-character random string
- Add GenerateRandomString function with alphanumeric charset

* feat: Refactor ID generation to use Snowflake IDs with prefixes and add domain-specific ID generators

- Replace timestamp-based GenerateRuleID with Snowflake-based GeneratePrefixed("rule")
- Replace random string-based GenerateEventID with Snowflake-based GeneratePrefixed("evt")
- Add GenerateUsageID with resourceType and tenantID parameters for traceable usage IDs
- Add GenerateAPIID, GenerateTenantID, GenerateProfileID, GenerateSubscriptionID, GenerateCarrierID, GeneratePricingID generators

* feat: Add tenant-aware rate limiter with sliding window counters and plan-based limits

- Add TenantRateLimiter with plan-based rate limits for Free, Basic, Pro, and Enterprise tiers
- Add RateLimit struct with RequestsPerMinute, RequestsPerHour, RequestsPerDay, and BurstSize fields
- Add TenantUsageTracker with sliding window counters for minute, hour, and day tracking
- Add SlidingWindowCounter with Allow and Count methods for time-based request tracking
- Add AllowRequest method with multi-tier rate limit

* feat: Implement tenant-aware currency service wrapper with billing isolation and audit logging

- Add TenantAwareCurrencyService struct with tenantID, billingService, and logger fields
- Add ProcessBilling method with tenant context logging for billing requests
- Add ConvertAmount method with tenant context logging for currency conversions
- Add GetBillingHistory method with tenant context logging for transaction retrieval
- Add CalculateTotalBilling method with tenant context logging for billing summ

* feat: Implement carrier weight updates, pricing analytics calculations, and tenant rate limiting

- Add updateCarrierWeights implementation with regional and plan-based weight adjustments in carrier_methods.go
- Add calculateRegionalWeightAdjustment helper with usage-based weight scaling and clamping
- Add calculatePlanWeightAdjustment helper with plan usage analysis and adjustment limits
- Add calculateConversionRate helper in pricing_integration.go using discount statistics and active rule ratios

* feat: Implement refund processing and billing analytics endpoints in currency handlers

- Add ProcessRefund implementation with negative billing entry for refunds and transaction ID fallback
- Add GetBillingAnalytics implementation with date range filtering, billing summary calculation, and transaction history
- Add default 30-day date range for analytics with RFC3339 date parsing for custom ranges
- Replace NotImplemented responses with full BillingService integration

* feat: Implement carrier metrics persistence with dedicated metrics table and timestamp updates

- Replace mock logging with actual database persistence in UpdateCarrierMetrics
- Add carrier record timestamp update with updated_at field
- Add carrier_metrics table insertion with JSON-serialized metrics data
- Add metricsRecord struct with CarrierID, MetricsData, and RecordedAt fields
- Add zero-division protection for success rate calculation
- Update logging to use structured fields with WithField

* feat: Add tenant context injection to currency service methods for downstream isolation

- Replace TODO comments with context.WithValue calls injecting tenant_id in ProcessBilling
- Add tenant context injection in ConvertAmount for tenant-specific exchange rates
- Add tenant context injection in GetBillingHistory for repository-level filtering
- Add tenant context injection in CalculateTotalBilling for scoped calculations
- Update comments to reflect context-based isolation strategy

* feat: Implement rate limiting and resource access validation in tenant middleware

- Add RateLimit implementation with tenant context retrieval and plan-based rate limit checking
- Add rate limit exceeded logging with tenant_id and endpoint fields
- Add HTTP 429 response with error message and endpoint when rate limit exceeded
- Add ValidateResourceAccess implementation with tenant ownership verification
- Add context injection for validated_resource, validated_resource_id, and tenant_id

* refactor: Extract CRUD operations from pricing service into separate file and improve discount extraction logic

- Move CreateRule, GetRule, UpdateRule, DeleteRule, ListRules, CalculatePrice, and ApplyRules to pricing_service_crud.go
- Remove duplicate struct and constructor comments from pricing_service.go
- Replace hardcoded discount values in extractDiscountValue with actual rule Actions field parsing
- Add AdjustmentType-based discount calculation for Percentage, Fixed, Multiply, and Override

* feat: Implement MCC-based regional scoring with geographic grouping for carrier selection

- Replace neutral 50.0 score with MCC-to-region mapping logic in calculateRegionScore
- Add mccToRegion function mapping MCC first digit to region codes (EU, NA, AS, OC, AF, SA)
- Add sameRegionGroup function grouping regions into EMEA, AMER, and APAC clusters
- Add 90.0 score for exact MCC region match, 70.0 for same region group, 30.0 for distant regions
- Add MCC range documentation for Europe (2xx), North America (3xx

* feat: Implement revenue analytics calculation, resource performance tracking, and round-robin load balancing

- Add revenue calculation in GetRevenueAnalytics with active subscription base price aggregation
- Add date range filtering for revenue analytics with StartDate and EndDate support
- Add per-plan revenue, subscription count, and average revenue calculations
- Add error handling with partial result fallback for revenue queries
- Replace mock resource performance with event-based performance

* refactor: Replace interface{} with any and optimize slice operations

- Replace map[string]interface{} with map[string]any in UpdateCarrierMetrics
- Replace interface{} with any for GeneratedAt field in PricingEffectiveness struct
- Replace loop-based empty string checks with slices.Contains in ValidateConditions
- Replace range loop index initialization with range-only syntax in calculateAPIPerformance
- Add slices import for standard library slice utilities

* refactor: Update comments in tenant repository to reflect actual implementation

- Replace vague "separate table or log system" comment with specific tenant_events table reference in CreateEvent
- Replace "For now, update tenant settings" with clearer "Store configuration in tenant metadata field and update settings" in UpdateConfig
- Remove "For now, we'll use a simple approach" qualifier from CreateEvent comment

* feat: Add MVNO HTTP handlers with onboarding, management, and statistics endpoints

- Add Handler struct with StartOnboarding, GetMVNO, and ListMVNOs methods in handler.go
- Add ManagementHandler struct with GetMVNO, ListMVNOs, UpdateMVNOStatus, and GetMVNOStats methods in handler_management.go
- Add RegisterRoutes method for /mvno/onboarding, /mvno, and /mvno/:id route registration
- Add query parameter parsing for status, plan, and limit filters in ListMVNOs
- Add structured logging with mvno_id, status, and error

* feat: Add MVNO onboarding validator with business, plan, and technical validation

- Add OnboardingValidator struct with ValidateRequest and ValidateMVNO methods in validator.go
- Add business info validation with name length, ID format, email regex, and phone length checks
- Add plan validation with subscriber limits for Starter (1000) and Growth (10000) plans
- Add technical requirements validation with country code format and use case length checks
- Add compliance validation with country-specific regulatory checks and restricted country filtering
- Add technical feasibility validation

* feat: Add MVNO domain types with status, plan, config, and onboarding request models

- Add MVNO struct with ID, Name, BusinessID, Status, Plan, Config, and timestamps
- Add MVNOStatus enum with pending, review, approved, active, suspended, and terminated states
- Add MVNOPlan enum with starter, growth, scale, and enterprise tiers
- Add MVNOConfig struct with subscriber limits, country restrictions, carrier pool, and feature flags
- Add OnboardingRequest struct with business info, contact details, plan selection

* feat: Add MVNO onboarding monitor with progress tracking and metrics collection

- Add OnboardingMonitor struct with progress map and mutex for concurrent access
- Add UpdateProgress and GetProgress methods for tracking individual MVNO onboarding state
- Add GetAllProgress with map copy to prevent concurrent access issues
- Add GetActiveOnboardingCount and GetCompletedOnboardingCount for status aggregation
- Add GetAverageOnboardingTime calculation with completed onboarding duration tracking
- Add GetStepSuccess

* feat: Add MVNO onboarding service with step-based workflow execution and progress tracking

- Add OnboardingService struct with validator, provisioner, and monitor dependencies
- Add StartOnboarding method with request validation, MVNO record creation, and async workflow execution
- Add executeOnboarding method with sequential step processing, context cancellation support, and progress updates
- Add executeStep method with switch-based routing for validation, provisioning, carrier setup, billing

* feat: Add MVNO repository with CRUD operations, filtering, and statistics aggregation

- Add Repository interface with CreateMVNO, GetMVNO, UpdateMVNO, ListMVNOs, DeleteMVNO, and UpdateMVNOStatus methods
- Add GormRepository struct with db and logger dependencies for GORM-based persistence
- Add MVNOFilter struct with status, plan, business_id, limit, offset, and date range filtering
- Add GetMVNO and GetMVNOByBusinessID methods with record not found error handling
- Add ListMVNOs with dynamic query

* feat: Add MVNO provisioner with resource provisioning, carrier setup, billing, and API access configuration

- Add MVNOProvisioner struct with logger dependency for resource provisioning operations
- Add ProvisionResources method with tenant context, database schema, and storage provisioning
- Add SetupCarriers method with carrier selection, configuration, and carrier pool assignment
- Add SetupBilling method with billing ID generation, rate plan configuration, and payment processing setup
- Add SetupAPIAcc

* feat: Add MVNO router with route setup, middleware configuration, and health check endpoint

- Add Router struct with handler and logger dependencies for routing configuration
- Add NewRouter constructor with repository, service, and handler initialization
- Add SetupRoutes method with /api/v1 versioning, logging, and recovery middleware
- Add SetupMiddleware with CORS headers, rate limiting placeholder, and request ID tracking
- Add HealthCheck method with service status, name, and version response

* feat: Add MVNO provisioner methods with tenant setup, resource allocation, carrier configuration, and validation

- Add provisionTenantContext with tenant config creation, settings mapping, and tenant service integration
- Add provisionDatabaseSchema with dedicated schema creation for MVNO isolation
- Add provisionStorageResources with plan-based storage allocation (10GB to 10TB)
- Add selectCarriers with country-based carrier selection, active status filtering, and duplicate prevention
- Add config

* feat: Add production MVNO provisioner with tenant, carrier, billing, and API access setup

- Add ProductionProvisioner struct with tenant, carrier, billing, and storage service dependencies
- Add TenantService, CarrierManager, BillingService, and StorageService interfaces for external integrations
- Add TenantConfig and CarrierInfo structs for tenant and carrier data models
- Add NewProductionProvisioner constructor with service dependency injection
- Add ProvisionResources method with tenant context

* feat: Add carrier-connector HTTP handlers with MVNO onboarding, management, and statistics endpoints

- Add Handler struct with StartOnboarding, GetMVNO, and ListMVNOs methods in handler_mvno.go
- Add ManagementHandler struct with GetMVNO, ListMVNOs, UpdateMVNOStatus, and GetMVNOStats methods in handler_management.go
- Add RegisterRoutes method for /mvno/onboarding, /mvno, and /mvno/:id route registration
- Add query parameter parsing for status, plan, and limit filters in ListMVNOs
- Add structured logging

* feat: Refactor MVNO handlers to use domain types and interface-based service dependency

- Rename Handler to MVNOHandler for clarity in handler_mvno.go
- Replace services.OnboardingService with OnboardingService interface for dependency injection
- Change monitor.OnboardingRequest, monitor.MVNOStatus, monitor.MVNOFilter, and monitor.MVNOPlan to mvno package types
- Remove monitor package import from handler_management.go and handler_mvno.go
- Add context.Context import for service method signatures

* feat: Add MVNO onboarding service with step-based workflow execution and progress tracking

- Add OnboardingService struct with validator, provisioner, and monitor dependencies
- Add NewOnboardingService constructor with logger dependency injection
- Add StartOnboarding method with request validation, MVNO record creation, and async workflow execution
- Add executeOnboarding method with sequential step processing, context cancellation support, and progress updates
- Add executeStep method with switch

* feat: Refactor step status checking from if-else to switch statement in GetStepSuccessRate

- Replace if-else chain with switch statement for step.Status evaluation in monitor.go
- Maintain completed and failed case handling with cleaner control flow

* feat: Extract repository interfaces from types.go into separate interfaces.go file

- Move TenantRepository and Repository interfaces from types.go to new interfaces.go file
- Add mvno package import for MVNO-related repository methods
- Add CreateMVNO, GetMVNO, GetMVNOByBusinessID, UpdateMVNO, ListMVNOs, DeleteMVNO, UpdateMVNOStatus, and GetMVNOStats methods to Repository interface
- Remove context import from types.go after interface extraction

* feat: Add MVNO repository with CRUD operations, filtering, and statistics aggregation

- Add MVNORepository implementation with CreateMVNO, GetMVNO, UpdateMVNO, ListMVNOs, DeleteMVNO, and UpdateMVNOStatus methods
- Add MVNOFilter struct with status, plan, business_id, limit, offset, and date range filtering
- Add GetMVNO and GetMVNOByBusinessID methods with record not found error handling
- Add ListMVNOs with dynamic query building, filter application, and descending created_at ordering
- Add GetMVNOStats with total count, status distribution, and plan distribution aggregation

* feat: Reorder OnboardingProgress and OnboardingStep structs and add MVNOFilter type

- Move OnboardingProgress struct definition before OnboardingStep for logical ordering
- Add MVNOFilter struct with status, plan, business_id, limit, offset, and date range filtering fields

* feat: Add logger dependency to SelectionService and refactor handler initialization

- Add logrus import and logger initialization in NewSelectionIntegration
- Pass logger instance to NewSelectionService constructor
- Replace selectionService.GetHandler() with direct handlers.NewSelectionHandler(manager) call

* feat: Remove MVNO handlers, service, and repository implementations from carrier-connector

- Delete handler.go with StartOnboarding, GetMVNO, ListMVNOs, and RegisterRoutes methods
- Delete handler_management.go with GetMVNO, ListMVNOs, UpdateMVNOStatus, and GetMVNOStats endpoints
- Delete onboarding_service.go with StartOnboarding, executeOnboarding, executeStep workflow orchestration
- Delete repository.go with GormRepository CRUD operations, filtering, and statistics methods
- Update provisioner.go to use map[string]any instead of map[string]interface{}

* feat: Remove MVNO router and add placeholder endpoints to main routes

- Delete router.go with Router struct, NewRouter constructor, SetupRoutes, SetupMiddleware, HealthCheck, and RegisterHealthCheck methods
- Add /mvno route group with POST /onboarding, GET /, GET /:id, PUT /:id/status, and GET /stats placeholder endpoints
- Replace router-based MVNO setup with direct route registration returning http.StatusNotImplemented responses

* feat: Wire MVNO handlers with repository and service dependencies in carrier-connector routes

- Add logrus and gorm imports to main.go for MVNO infrastructure setup
- Create logger instance and separate database connection for MVNO repository in main
- Initialize GormRepository with database connection and logger
- Pass repo and logger to setupRoutes for MVNO handler initialization
- Replace placeholder MVNO endpoints with actual handler methods in routes.go
- Create OnboardingService, MVNOHandler, and ManagementHandler instances

* feat: Add comprehensive routing for rate plans, pricing, currency, tenants, SMDP, and selection endpoints

- Add db parameter to setupRoutes function signature and pass from main.go
- Add rate plan routes with CRUD, search, subscription, and management endpoints using RatePlanAdapter
- Add pricing routes with rule management endpoints using PricingService
- Add currency routes with conversion, exchange rates, billing operations, and analytics placeholder endpoints
- Add tenant routes with management

* feat: Add RatePlanAdapter with CRUD operations, subscription management, usage tracking, and analytics

- Add RatePlanAdapter struct wrapping Service to implement rateplan.Service interface
- Add NewRatePlanAdapter constructor returning rateplan.Service
- Add CreateRatePlan, GetRatePlan, UpdateRatePlan, DeleteRatePlan, ListRatePlans, SearchRatePlans, and GetPopularPlans methods with type conversions
- Add SubscribeToPlan, GetSubscription, UpdateSubscription, CancelSubscription, GetActiveSubscription

* feat: Extract domain route registration from setupRoutes into separate functions in routes_domain.go

- Move rate plan, pricing, currency, tenant, and SMDP route registration from routes.go to new routes_domain.go file
- Add registerMVNORoutes, registerRatePlanRoutes, registerPricingRoutes, registerCurrencyRoutes, registerTenantRoutes, and registerSMDPRoutes functions
- Simplify setupRoutes to call domain-specific registration functions with required dependencies
- Remove nested route group blocks in favor

* refactor: Replace unused context parameters with blank identifiers and fix variable references

- Replace ctx parameter with _ in provisionTenantContext, provisionDatabaseSchema, provisionStorageResources, configureCarrier, configureRatePlans, setupPaymentProcessing, and validateCompliance methods
- Fix tenant_id scope to use wrappedTx.tenantID instead of r.tenantID in TenantScopedTransaction
- Fix pricing effectiveness analytics to use ratePlanAnalytics.AverageDiscount and ratePlanAnalytics.TotalSavings instead of analytics.

* feat: Add analytics service with dashboard metrics, revenue tracking, and scheduled reporting

- Add Service struct with GetDashboard, GetRevenueAnalytics, CreateScheduledReport, and ListScheduledReports methods
- Add getRevenueMetrics, getSubscriberStats, getUsageMetrics, getCarrierMetrics, getGeoMetrics, and getPerformanceStats helper methods
- Add DashboardMetrics, RevenueMetrics, SubscriberStats, UsageMetrics, CarrierMetrics, GeoMetrics, and PerformanceStats types
- Add CarrierStat, CountryStat, RegionStat

* feat: Add compliance service with DSR management, consent tracking, audit logging, and data residency

- Add Service struct with db and logger dependencies and NewService constructor
- Add CreateDSR, GetDSR, ListDSRs, and ProcessDSR methods for data subject request lifecycle management
- Add processAccessRequest, processErasureRequest, processRectificationRequest, and calculateDueDate helper methods
- Add RecordConsent, RevokeConsent, and GetConsents methods for consent management
- Add LogAudit

* feat: Add in-memory cache with TTL, LRU eviction, JSON serialization, and statistics tracking

- Add Cache struct with entries map, mutex, maxSize, defaultTTL, strategy, and stats fields
- Add CacheStrategy type with LRU, TTL, write-through, write-back, and read-through constants
- Add CacheEntry struct with Key, Value, ExpiresAt, CreatedAt, and HitCount fields
- Add NewCache constructor with CacheConfig parameter and automatic cleanup goroutine
- Add Get, Set, Delete, and Clear methods with hit

* feat: Add circuit breaker with state management, failure tracking, fallback support, and statistics

- Add CircuitState type with StateClosed, StateOpen, and StateHalfOpen constants and String method
- Add CircuitBreaker struct with name, state, failureCount, successCount, lastFailure, config, mutex, and onStateChange fields
- Add CircuitBreakerConfig with FailureThreshold, SuccessThreshold, Timeout, and HalfOpenMaxCalls fields
- Add NewCircuitBreaker constructor and DefaultCircuitBreakerConfig with

* feat: Add whitelabel service with branding, partner config, and email template management

- Add Service struct with db and logger dependencies and NewService constructor
- Add CreateBranding, GetBranding, GetBrandingByDomain, and UpdateBranding methods for branding configuration management
- Add CreatePartnerConfig and GetPartnerConfig methods for partner-specific settings
- Add CreateEmailTemplate, GetEmailTemplate, and ListEmailTemplates methods for custom email template management
- Add BrandingConfig with

* feat: Add real-time exchange rate service with multi-provider support, caching, and automatic refresh

- Add ExchangeRateProvider type with OpenExchange, Fixer, XE, and Internal constants
- Add RealTimeExchangeService struct with provider, apiKey, baseCurrency, rates cache, lastUpdate, cacheTTL, mutex, logger, and httpClient fields
- Add ExchangeRateConfig with Provider, APIKey, BaseCurrency, and CacheTTL fields
- Add NewRealTimeExchangeService constructor with default 15-minute cache TTL and USD

* feat: Add analytics handler with dashboard, revenue analytics, and scheduled report endpoints

- Add AnalyticsHandler struct with service and logger dependencies and NewAnalyticsHandler constructor
- Add GetDashboard method with tenant ID extraction, date range filtering, and dashboard metrics retrieval
- Add GetRevenueAnalytics method with tenant filtering and group-by support
- Add CreateScheduledReport and ListScheduledReports methods for report management
- Add date parsing for start_date and end_date query

* feat: Add threat detection service with brute force, rate limit abuse, SQL injection detection, and IP tracking

- Add ThreatLevel type with Low, Medium, High, and Critical constants
- Add ThreatType type with BruteForce, RateLimitAbuse, SQLInjection, XSS, Unauthorized, DataExfil, and Anomalous constants
- Add ThreatEvent struct with ID, TenantID, Type, Level, Source, Target, Description, Metadata, DetectedAt, Mitigated, and MitigatedAt fields
- Add ThreatDetector struct with logger, rules, events, ip

* feat: Add compliance handler with DSR management, consent tracking, audit logging, and data residency endpoints

- Add ComplianceHandler struct with service and logger dependencies and NewComplianceHandler constructor
- Add CreateDSR, GetDSR, ListDSRs, and ProcessDSR methods for data subject request management
- Add RecordConsent, RevokeConsent, and GetConsents methods for consent tracking with IP and user agent capture
- Add QueryAuditLogs method with jurisdiction, actor, and action filtering
- Add SetDataRes

* feat: Add geographic routing service with region management, IP-based routing, and endpoint selection

- Add GeoRouter struct with regions map, defaultReg, and mutex fields
- Add Region struct with ID, Name, Endpoints, Priority, IsActive, and Latency fields
- Add GeoRoutingConfig with DefaultRegion and Regions fields
- Add NewGeoRouter constructor with region initialization
- Add GetRegionForIP method with IP parsing and geo lookup
- Add lookupRegion helper with simplified IP range-based region detection

* feat: Add whitelabel handler with branding, partner config, and email template endpoints

- Add WhitelabelHandler struct with service and logger dependencies and NewWhitelabelHandler constructor
- Add CreateBranding, GetBranding, GetBrandingByDomain, and UpdateBranding methods for branding configuration management
- Add CreatePartnerConfig and GetPartnerConfig methods for partner-specific settings
- Add CreateEmailTemplate, GetEmailTemplate, and ListEmailTemplates methods for email template management

* feat: Add encryption service with AES-GCM, field-level encryption, and PBKDF2 key derivation

- Add EncryptionService struct with masterKey and gcm cipher fields
- Add EncryptionConfig with MasterKey and KeyDerivationSalt fields
- Add NewEncryptionService constructor with PBKDF2 key derivation, 100000 iterations, and AES-GCM cipher initialization
- Add Encrypt and Decrypt methods with nonce generation and validation
- Add EncryptString and DecryptString methods with base64 encoding
- Add FieldEncryptor struct

* feat: Fix type conversions, rename ExchangeRateProvider to RateProviderType, and improve currency integration

- Fix GetRevenueAnalytics return type by dereferencing metrics struct
- Fix getCarrierMetrics to use int64 for Count and convert to int for ActiveCarriers
- Rename ExchangeRateProvider to RateProviderType for consistency
- Change RatePlanCurrencyIntegrator.exchangeService from pointer to interface type
- Add function documentation comments for NewRatePlanCurrencyIntegrator, SubscribeToPlanWith

* feat: Add platform routes with analytics, whitelabel, compliance, exchange rate, and infrastructure endpoints

- Add registerAnalyticsRoutes, registerWhitelabelRoutes, registerComplianceRoutes, registerExchangeRateRoutes, and registerInfraRoutes to setupRoutes
- Add routes_platform.go with analytics dashboard, revenue analytics, and scheduled report endpoints
- Add whitelabel branding, partner config, and email template endpoints
- Add compliance DSR, consent management, audit logging, and data residency endpoints

* feat: Add churn analysis service with risk prediction, metrics calculation, and retention recommendations

- Add ChurnRiskLevel type with Low, Medium, High, and Critical constants
- Add ChurnPrediction struct with ProfileID, RiskLevel, RiskScore, PredictedChurnDate, Reasons, Recommendations, and LastUpdated fields
- Add ChurnMetrics struct with Period, TotalSubscribers, ChurnedSubscribers, ChurnRate, MonthlyChurnRate, AnnualChurnRate, AverageTenure, and RiskDistribution fields
- Add ChurnFactor struct with Factor

* feat: Add market analysis service with penetration metrics, competitor analysis, and opportunity identification

- Add MarketMetrics struct with Period, TotalMarketSize, OurSubscribers, MarketShare, GrowthRate, ByCountry, ByCarrier, ByDemographic, CompetitorAnalysis, and PenetrationOpportunities fields
- Add CountryMetrics struct with Country, TotalPopulation, ActiveSubscribers, PenetrationRate, GrowthRate, ARPU, and MarketPotential fields
- Add MarketCarrierMetrics struct with CarrierName, Subscribers

* feat: Add fraud detection service with pattern matching, ML models, risk scoring, and automated blocking

- Add FraudType constants for account_takeover, subscription_fraud, payment_fraud, usage_anomaly, identity_fraud, and sim_swap
- Add FraudSeverity type with Low, Medium, High, and Critical levels
- Add FraudAlert struct with ID, Type, Severity, ProfileID, RiskScore, Evidence, IPAddress, UserAgent, Location, Status, Actions, and Metadata fields
- Add FraudPattern struct with pattern configuration and weight-based scoring
- Add FraudDetectionService with patterns, alerts

* feat: Add predictive maintenance service with asset monitoring, failure prediction, ML models, and health scoring

- Add MaintenanceType constants for preventive, corrective, predictive, and emergency maintenance
- Add AssetType constants for server, database, network, storage, application, and load_balancer
- Add Asset struct with ID, Name, Type, Status, Location, HealthScore, LastMaintenance, NextMaintenance, and Metadata fields
- Add MaintenanceAlert struct with ID, AssetID, Type, Severity, Title, Description, RiskScore,

* feat: Add pricing optimization service with strategy-based pricing, demand prediction, and performance metrics

- Add OptimizationStrategy constants for revenue_maximization, market_share, profit_margin, competitive, and churn_reduction
- Add OptimizationResult struct with RatePlanID, Strategy, CurrentPrice, OptimalPrice, PriceChange, ExpectedRevenue, ExpectedDemand, Confidence, Reasoning, Risks, and Recommendations fields
- Add PricingMetrics struct with Period, TotalRevenue, TotalSubscribers, AR

* feat: Remove fraud detection service and move to dedicated security module

- Remove FraudDetectionService with pattern matching, ML models, risk scoring, and automated blocking
- Remove FraudType constants for account_takeover, subscription_fraud, payment_fraud, usage_anomaly, identity_fraud, and sim_swap
- Remove FraudSeverity type with Low, Medium, High, and Critical levels
- Remove FraudAlert struct with ID, Type, Severity, ProfileID, RiskScore, Evidence, IPAddress, UserAgent, Location, Status

* feat: Refactor churn analysis service to simplify logic and extract reusable components

- Remove ChurnRiskLevel, ChurnPrediction, ChurnMetrics, and ChurnFactor type definitions from churn_service.go
- Simplify NewChurnAnalysisService constructor to single-line initialization
- Refactor PredictChurn to use analyzeFactors, calculateScore, RiskLevelFromScore, generateReasons, and RecommendationsForRisk helper functions
- Simplify GetChurnMetrics by using periodDates helper and inline database queries
- Replace GetChurnFactors implementation with DefaultChurnFactors helper

* feat: Add churn analysis types with risk levels, predictions, metrics, and helper functions

- Add ChurnRiskLevel type with Low, Medium, High, and Critical constants
- Add ChurnPrediction struct with ProfileID, RiskLevel, RiskScore, PredictedChurnDate, Reasons, Recommendations, and LastUpdated fields
- Add ChurnMetrics struct with Period, TotalSubscribers, ChurnedSubscribers, ChurnRate, MonthlyChurnRate, AnnualChurnRate, AverageTenure, and RiskDistribution fields
- Add ChurnFactor struct with Factor, Impact, Description, and Weight fields

* feat: Refactor rate plan currency integrator to simplify subscription creation and remove unused helper

- Simplify SubscribeToPlanWithCurrency by creating SubscribeRequest directly instead of intermediate RatePlanSubscription struct
- Remove redundant Status, StartedAt, CreatedAt, and UpdatedAt field assignments
- Mark unused context parameters with underscore in calculateOverageCost and generateReason
- Remove unused getHighestPriorityCarrier helper function from selection_algorithm.go

* feat: Mark unused parameters with underscore, remove unused file, and add subscriber journey E2E tests

- Mark unused context and filter parameters with underscore in getCarrierMetrics, getGeoMetrics, and getPerformanceStats
- Remove unused RatePlanCurrencyIntegrator service from currency/services/rateplan_core.go
- Simplify ML model weight comparison in selection_test_ml.go by using literal values instead of originalWeights variable
- Add comprehensive subscriber_journey_test.go with full lifecycle

* feat: Update README with multi-language SDK support and analytics services documentation

- Replace TypeScript SDK reference with Multi-Language SDKs supporting Go, Python, TypeScript, Kotlin, Ruby, Swift, Rust, and Elixir
- Add Analytics & Intelligence section documenting Churn Analysis, Fraud Detection, Market Analytics, Predictive Maintenance, and Pricing Optimization services
- Add SDK Documentation link to docs/sdk-usage.md in Documentation section

* feat: Add pricing optimization service with elasticity calculations, strategy-based pricing, and demand prediction

- Add calculatePriceElasticity using log-linear regression with realistic telecom bounds (-2.0 to -0.3)
- Add optimizeForRevenue using revenue optimization formula with elasticity-based pricing
- Add optimizeForMarketShare with penetration strategy and aggressive pricing based on elasticity
- Add optimizeForProfitMargin using cost-plus analysis with 40% target margin
- Add optimizeForComp

* feat: Refactor pricing optimization service by extracting helper functions to separate file

- Move calculateElasticity, calculateCompetitiveIndex, and calculateOptimizationROI to optimization_opt_service.go
- Move generateAnalysis, calculateConfidence, and calculateChurnRate to optimization_opt_service.go
- Simplify calculatePriceElasticity by removing comments and consolidating logic
- Simplify optimizeForRevenue, optimizeForMarketShare, optimizeForProfitMargin, optimizeForCompetitive, and optimizeForChurn

* feat: Add security handler with fraud detection, SIM swap verification, and alert management

- Add SecurityHandler with fraud analysis, alert filtering, and metrics endpoints
- Add FraudAlert struct with ID, Type, Severity, ProfileID, RiskScore, Evidence, IPAddress, Status, and ActionsTaken fields
- Add FraudMetrics struct with Period, TotalAlerts, ResolvedAlerts, ResolutionRate, FalsePositiveRate, ByType, and BySeverity fields
- Add AnalyzeTransaction with risk scoring based on transaction amount and suspicious

* feat: Add analytics handlers for market analysis, maintenance metrics, and pricing optimization

- Add GetChurnMetrics with period-based churn rate, subscriber counts, and risk distribution
- Add GetCompetitors with market share, strengths, weaknesses, and threat levels
- Add GetMarketOpportunities with potential subscribers, ROI, and confidence scores
- Add GetMaintenanceMetrics with asset health, uptime, MTTR, and MTTF tracking
- Add GetAssetsHealth returning health scores and status for servers

* feat: Add analytics handler with churn prediction, market metrics, and analytics types

- Add AnalyticsHandler with NewAnalyticsHandler constructor
- Add PredictChurn endpoint returning risk level, score, predicted date, reasons, and recommendations
- Add GetAtRiskCustomers with risk level filtering and configurable limit (max 1000)
- Add GetMarketMetrics returning market size, subscribers, share, growth rate, and country breakdown
- Add ChurnPrediction struct with ProfileID, RiskLevel, RiskScore

* feat: Add currency handler with conversion, exchange rates, billing, and analytics endpoints

- Add CurrencyHandler with NewCurrencyHandler constructor
- Add ConvertCurrency with multi-currency support (USD, EUR, GBP, JPY, CAD, AUD, CHF)
- Add GetExchangeRate, GetExchangeRateHistory with 30-day historical data, and RefreshExchangeRates endpoints
- Add GetSupportedCurrencies returning code, name, and symbol for 10 currencies
- Add ProcessBilling with charge/credit/refund types and transaction creation

* feat: Add analytics, security, and currency route handlers with comprehensive endpoint registration

- Add registerAnalyticsRoutes with churn analysis (predict, metrics, at-risk), market analytics (metrics, competitors, opportunities), predictive maintenance (metrics, assets, alerts, predict), and pricing optimization (metrics, optimize, elasticity) endpoints
- Add registerSecurityRoutes with fraud detection (analyze, alerts, update status, metrics, patterns) and SIM swap protection (verify, history) endpoints

* feat: Mark unused context parameters with underscore and refactor fraud metrics status handling

- Mark unused context parameters with underscore in analyzeCompetitors, identifyOpportunities, and PredictFailure
- Replace if-else chain with switch statement for fraud alert status handling in GetFraudMetrics
- Add OptimizationResult, PricingMetrics, RatePlan, and HistoricalDataPoint types to pricing/types.go

* feat: Add analytics handler with revenue metrics, usage analytics, billing analytics, churn risk, and pricing recommendations

- Add RevenueMetrics with total revenue, ARPU, MRR, ARR, growth percentage, and breakdowns by plan and region
- Add UsageAnalytics with data/voice/SMS totals, average per user, peak usage hour, and trend tracking
- Add BillingAnalytics with invoiced/collected amounts, collection rate, outstanding balance, payment days, and payment method breakdown
- Add ChurnRiskScore with risk level, score, contributing

* feat: Add analytics CLI commands with churn, fraud, market, pricing, and maintenance subcommands

- Add NewAnalyticsCmd with churn, fraud, market, pricing, and maintenance command groups
- Add churn commands: predict, metrics, at-risk with risk-level, period, and limit flags
- Add fraud commands: alerts, metrics, patterns with severity and type filtering
- Add market commands: metrics, competitors, opportunities for market analytics
- Add pricing commands: metrics, optimize with strategy-based optimization
- Add maintenance commands: metrics, assets, predict for predictive maintenance
- Add spf

* feat: Add analytics and churn dashboard pages with metrics visualization, risk analysis, and multi-tab interfaces

- Add analytics page with overview, churn, market, maintenance, and pricing tabs
- Add churn page with predictions table, risk filtering, and retention recommendations
- Add metrics cards for subscribers, churn rate, market share, and system uptime
- Add risk distribution visualization with progress bars and color-coded badges
- Add market metrics with country breakdown and penetration rates
- Add maintenance metrics with asset health, MTTF, MTTR

* feat: Add analytics, security, and currency SDK modules with comprehensive API endpoints across Elixir and Go SDKs

- Add AnalyticsAPI with churn prediction (predict, metrics, at-risk), market analytics (metrics, competitors, opportunities), predictive maintenance (metrics, assets, alerts, predict), and pricing optimization (metrics, optimize, elasticity) endpoints
- Add SecurityAPI with fraud detection (analyze, alerts, update status, metrics, patterns) and SIM swap protection (verify, history) endpoints
- Add CurrencyAPI with currency conversion (convert, exchange rates, rate

* feat: Add analytics configuration to Helm values with churn, fraud, market, maintenance, and pricing modules

- Add platform version 2.0.0 to global configuration
- Add analytics configuration with enabled flag
- Add churn module with xgboost ML model, daily prediction interval, and risk thresholds (low: 25, medium: 50, high: 75)
- Add fraud module with real-time detection, severity levels (low/medium/high/critical), and patterns (account_takeover, subscription_fraud, payment_fraud, usage_anomaly, sim_swap)
- Add market module with competitor tracking and weekly update interval
- Add maintenance module with LSTM predictive model and 0.7 alert threshold

* docs: Add comprehensive SDK documentation and API endpoint reference to README

- Add sdk/ directory structure with Go, Python, TypeScript, Kotlin, Ruby, Swift, Rust, and Elixir SDKs
- Add docs/sdk-usage.md reference to documentation section
- Add Analytics API endpoints table with churn prediction, market analysis, maintenance metrics, and pricing optimization
- Add Security API endpoints table with fraud detection, alert management, and SIM swap protection
- Add Currency & Billing API endpoints table with conversion

* docs: Add comprehensive platform architecture and components documentation to README

- Add API Gateway Layer section with Traefik, unified HTTPS endpoint, security middleware, and monitoring dashboard
- Add Core Network Services with API Server, Carrier Connector, Charging Engine, and Packet Gateway descriptions
- Add Supporting Infrastructure section covering PostgreSQL, Redis, MongoDB, RabbitMQ, Consul, and Vault
- Add Frontend Applications section with Web Dashboard features and architecture
2026-05-03 13:36:31 +03:00

745 lines
22 KiB
Go

package e2e
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
"github.com/sirupsen/logrus"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// SubscriberJourneyTestSuite tests end-to-end subscriber journey
type SubscriberJourneyTestSuite struct {
suite.Suite
db *gorm.DB
router *gin.Engine
logger *logrus.Logger
}
// SetupSuite sets up the test suite
func (suite *SubscriberJourneyTestSuite) SetupSuite() {
// Setup in-memory database for testing
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(suite.T(), err)
// Auto-migrate tables
err = db.AutoMigrate(
&repository.RatePlanUsage{},
&repository.RatePlanSubscription{},
)
require.NoError(suite.T(), err)
suite.db = db
suite.logger = logrus.New()
suite.logger.SetLevel(logrus.ErrorLevel)
// Setup router with full application routes
gin.SetMode(gin.TestMode)
suite.router = gin.New()
suite.setupRoutes()
}
func (suite *SubscriberJourneyTestSuite) setupRoutes() {
api := suite.router.Group("/api/v1")
// Profile management
profiles := api.Group("/profiles")
{
profiles.POST("", suite.createProfile)
profiles.GET("/:id", suite.getProfile)
profiles.PUT("/:id/activate", suite.activateProfile)
}
// Rate plan management
rateplans := api.Group("/rateplans")
{
rateplans.POST("", suite.createRatePlan)
rateplans.GET("", suite.listRatePlans)
rateplans.GET("/:id", suite.getRatePlan)
}
// Subscription management
subscriptions := api.Group("/subscriptions")
{
subscriptions.POST("", suite.createSubscription)
subscriptions.GET("/:id", suite.getSubscription)
subscriptions.PUT("/:id/cancel", suite.cancelSubscription)
subscriptions.POST("/:id/usage", suite.recordUsage)
subscriptions.GET("/:id/usage", suite.getUsage)
}
// Billing
billing := api.Group("/billing")
{
billing.POST("/charge", suite.processCharge)
billing.GET("/invoice/:subscription_id", suite.getInvoice)
}
// Analytics
analytics := api.Group("/analytics")
{
analytics.GET("/dashboard", suite.getDashboard)
analytics.GET("/revenue", suite.getRevenue)
}
}
// TestCompleteSubscriberJourney tests the full subscriber lifecycle
func (suite *SubscriberJourneyTestSuite) TestCompleteSubscriberJourney() {
// Step 1: Create a rate plan
ratePlanReq := map[string]interface{}{
"name": "Premium Data Plan",
"description": "Unlimited data with voice and SMS",
"currency": "USD",
"base_price": 29.99,
"billing_cycle": "monthly",
"features": []string{"unlimited_data", "unlimited_voice", "unlimited_sms"},
}
reqBody, _ := json.Marshal(ratePlanReq)
req := httptest.NewRequest(http.MethodPost, "/api/v1/rateplans", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var ratePlan map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &ratePlan)
require.NoError(suite.T(), err)
ratePlanID := fmt.Sprintf("%v", ratePlan["id"])
// Step 2: Create a subscriber profile
profileReq := map[string]interface{}{
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+1234567890",
"country": "US",
"status": "pending",
"metadata": map[string]interface{}{
"source": "web_signup",
},
}
reqBody, _ = json.Marshal(profileReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/profiles", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var profile map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &profile)
require.NoError(suite.T(), err)
profileID := fmt.Sprintf("%v", profile["id"])
// Step 3: Activate the profile
req = httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/v1/profiles/%s/activate", profileID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
// Step 4: Subscribe to a rate plan
subReq := map[string]interface{}{
"profile_id": profileID,
"rate_plan_id": ratePlanID,
"auto_renew": true,
"payment_method": "credit_card",
"billing_address": map[string]interface{}{
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "US",
},
}
reqBody, _ = json.Marshal(subReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/subscriptions", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var subscription repository.RatePlanSubscription
err = json.Unmarshal(w.Body.Bytes(), &subscription)
require.NoError(suite.T(), err)
assert.Equal(suite.T(), profileID, subscription.ProfileID)
assert.Equal(suite.T(), ratePlanID, subscription.RatePlanID)
assert.Equal(suite.T(), repository.SubscriptionStatus("active"), subscription.Status)
subscriptionID := subscription.ID
// Step 5: Record usage for the subscription
usageReq := map[string]interface{}{
"data_used": int64(5120), // 5GB in MB
"voice_used": int64(450), // 450 minutes
"sms_used": int64(25), // 25 SMS
"timestamp": time.Now().Format(time.RFC3339),
}
reqBody, _ = json.Marshal(usageReq)
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/v1/subscriptions/%s/usage", subscriptionID), bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
// Step 6: Get usage history
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/subscriptions/%s/usage", subscriptionID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var usageList []repository.RatePlanUsage
err = json.Unmarshal(w.Body.Bytes(), &usageList)
require.NoError(suite.T(), err)
assert.Greater(suite.T(), len(usageList), 0)
// Step 7: Process billing charge
chargeReq := map[string]interface{}{
"subscription_id": subscriptionID,
"amount": 29.99,
"currency": "USD",
"description": "Monthly subscription fee",
"charge_type": "recurring",
}
reqBody, _ = json.Marshal(chargeReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/billing/charge", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
// Step 8: Get invoice
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/billing/invoice/%s", subscriptionID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var invoice map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &invoice)
require.NoError(suite.T(), err)
assert.Equal(suite.T(), subscriptionID, fmt.Sprintf("%v", invoice["subscription_id"]))
assert.Equal(suite.T(), 29.99, invoice["total_amount"])
// Step 9: Check analytics dashboard
req = httptest.NewRequest(http.MethodGet, "/api/v1/analytics/dashboard", nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var dashboard map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &dashboard)
require.NoError(suite.T(), err)
assert.Contains(suite.T(), dashboard, "total_subscribers")
assert.Contains(suite.T(), dashboard, "monthly_revenue")
assert.Contains(suite.T(), dashboard, "active_subscriptions")
// Step 10: Cancel subscription (end of journey)
req = httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/v1/subscriptions/%s/cancel", subscriptionID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
// Verify subscription is cancelled
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/subscriptions/%s", subscriptionID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var cancelledSub repository.RatePlanSubscription
err = json.Unmarshal(w.Body.Bytes(), &cancelledSub)
require.NoError(suite.T(), err)
assert.Equal(suite.T(), repository.SubscriptionStatus("cancelled"), cancelledSub.Status)
}
// TestMultiSubscriptionJourney tests subscriber with multiple subscriptions
func (suite *SubscriberJourneyTestSuite) TestMultiSubscriptionJourney() {
// Create multiple rate plans
ratePlans := []map[string]interface{}{
{
"name": "Basic Plan",
"base_price": 9.99,
"currency": "USD",
"features": []string{"1gb_data", "100min_voice"},
},
{
"name": "Premium Plan",
"base_price": 29.99,
"currency": "USD",
"features": []string{"unlimited_data", "unlimited_voice"},
},
}
ratePlanIDs := []string{}
for _, rp := range ratePlans {
reqBody, _ := json.Marshal(rp)
req := httptest.NewRequest(http.MethodPost, "/api/v1/rateplans", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var ratePlan map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &ratePlan)
require.NoError(suite.T(), err)
ratePlanIDs = append(ratePlanIDs, fmt.Sprintf("%v", ratePlan["id"]))
}
// Create profile
profileReq := map[string]interface{}{
"first_name": "Jane",
"last_name": "Smith",
"email": "[email protected]",
"country": "US",
}
reqBody, _ := json.Marshal(profileReq)
req := httptest.NewRequest(http.MethodPost, "/api/v1/profiles", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
var profile map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &profile)
require.NoError(suite.T(), err)
profileID := fmt.Sprintf("%v", profile["id"])
// Activate profile
req = httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/v1/profiles/%s/activate", profileID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
// Subscribe to multiple plans
subscriptionIDs := []string{}
for i, ratePlanID := range ratePlanIDs {
subReq := map[string]interface{}{
"profile_id": profileID,
"rate_plan_id": ratePlanID,
"auto_renew": true,
"metadata": map[string]interface{}{
"priority": i + 1,
},
}
reqBody, _ = json.Marshal(subReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/subscriptions", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
var subscription repository.RatePlanSubscription
err = json.Unmarshal(w.Body.Bytes(), &subscription)
require.NoError(suite.T(), err)
subscriptionIDs = append(subscriptionIDs, subscription.ID)
}
// Verify all subscriptions are active
for _, subID := range subscriptionIDs {
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/subscriptions/%s", subID), nil)
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var sub repository.RatePlanSubscription
err = json.Unmarshal(w.Body.Bytes(), &sub)
require.NoError(suite.T(), err)
assert.Equal(suite.T(), repository.SubscriptionStatus("active"), sub.Status)
}
// Record usage on primary subscription
usageReq := map[string]interface{}{
"data_used": int64(2048),
"voice_used": int64(150),
"sms_used": int64(10),
}
reqBody, _ = json.Marshal(usageReq)
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/v1/subscriptions/%s/usage", subscriptionIDs[0]), bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusCreated, w.Code)
// Check analytics reflects multiple subscriptions
req = httptest.NewRequest(http.MethodGet, "/api/v1/analytics/dashboard", nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusOK, w.Code)
var dashboard map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &dashboard)
require.NoError(suite.T(), err)
// Should have at least 1 active subscriber
totalSubs := dashboard["total_subscribers"].(int64)
assert.Greater(suite.T(), totalSubs, int64(0))
}
// TestFailedJourneyHandling tests error scenarios in subscriber journey
func (suite *SubscriberJourneyTestSuite) TestFailedJourneyHandling() {
// Test subscription without active profile
subReq := map[string]interface{}{
"profile_id": "non-existent-profile",
"rate_plan_id": "non-existent-plan",
"auto_renew": true,
}
reqBody, _ := json.Marshal(subReq)
req := httptest.NewRequest(http.MethodPost, "/api/v1/subscriptions", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusBadRequest, w.Code)
var errorResp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &errorResp)
require.NoError(suite.T(), err)
assert.Contains(suite.T(), errorResp, "error")
// Test usage recording for non-existent subscription
usageReq := map[string]interface{}{
"data_used": int64(100),
"voice_used": int64(10),
"sms_used": int64(5),
}
reqBody, _ = json.Marshal(usageReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/subscriptions/non-existent/usage", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusNotFound, w.Code)
// Test billing for cancelled subscription
// First create and cancel a subscription
profileReq := map[string]interface{}{
"email": "[email protected]",
"country": "US",
}
reqBody, _ = json.Marshal(profileReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/profiles", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
var profile map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &profile)
require.NoError(suite.T(), err)
profileID := fmt.Sprintf("%v", profile["id"])
// Activate
req = httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/v1/profiles/%s/activate", profileID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
// Create rate plan
rpReq := map[string]interface{}{
"name": "Test Plan",
"currency": "USD",
"base_price": 10.0,
}
reqBody, _ = json.Marshal(rpReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/rateplans", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
var ratePlan map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &ratePlan)
require.NoError(suite.T(), err)
ratePlanID := fmt.Sprintf("%v", ratePlan["id"])
// Subscribe
subReq = map[string]interface{}{
"profile_id": profileID,
"rate_plan_id": ratePlanID,
"auto_renew": true,
}
reqBody, _ = json.Marshal(subReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/subscriptions", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
var subscription repository.RatePlanSubscription
err = json.Unmarshal(w.Body.Bytes(), &subscription)
require.NoError(suite.T(), err)
// Cancel subscription
req = httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/v1/subscriptions/%s/cancel", subscription.ID), nil)
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
// Try to bill cancelled subscription
chargeReq := map[string]interface{}{
"subscription_id": subscription.ID,
"amount": 10.0,
"currency": "USD",
}
reqBody, _ = json.Marshal(chargeReq)
req = httptest.NewRequest(http.MethodPost, "/api/v1/billing/charge", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
w = httptest.NewRecorder()
suite.router.ServeHTTP(w, req)
assert.Equal(suite.T(), http.StatusBadRequest, w.Code)
}
// Handler implementations (simplified for testing)
func (suite *SubscriberJourneyTestSuite) createProfile(c *gin.Context) {
profile := map[string]interface{}{
"id": fmt.Sprintf("profile-%d", time.Now().UnixNano()),
"status": "pending",
"created_at": time.Now(),
}
// Add request fields
var req map[string]interface{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for k, v := range req {
profile[k] = v
}
c.JSON(http.StatusCreated, profile)
}
func (suite *SubscriberJourneyTestSuite) getProfile(c *gin.Context) {
profile := map[string]interface{}{
"id": c.Param("id"),
"status": "active",
}
c.JSON(http.StatusOK, profile)
}
func (suite *SubscriberJourneyTestSuite) activateProfile(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "activated"})
}
func (suite *SubscriberJourneyTestSuite) createRatePlan(c *gin.Context) {
ratePlan := map[string]interface{}{
"id": fmt.Sprintf("plan-%d", time.Now().UnixNano()),
"created_at": time.Now(),
}
var req map[string]interface{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for k, v := range req {
ratePlan[k] = v
}
c.JSON(http.StatusCreated, ratePlan)
}
func (suite *SubscriberJourneyTestSuite) listRatePlans(c *gin.Context) {
plans := []map[string]interface{}{
{
"id": "plan-1",
"name": "Basic Plan",
"price": 9.99,
},
{
"id": "plan-2",
"name": "Premium Plan",
"price": 29.99,
},
}
c.JSON(http.StatusOK, plans)
}
func (suite *SubscriberJourneyTestSuite) getRatePlan(c *gin.Context) {
ratePlan := map[string]interface{}{
"id": c.Param("id"),
"name": "Test Plan",
}
c.JSON(http.StatusOK, ratePlan)
}
func (suite *SubscriberJourneyTestSuite) createSubscription(c *gin.Context) {
var subscription repository.RatePlanSubscription
if err := c.ShouldBindJSON(&subscription); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
subscription.ID = fmt.Sprintf("sub-%d", time.Now().UnixNano())
subscription.Status = repository.SubscriptionStatus("active")
subscription.StartedAt = time.Now()
subscription.CreatedAt = time.Now()
subscription.UpdatedAt = time.Now()
subscription.CurrentCycle = time.Now()
c.JSON(http.StatusCreated, subscription)
}
func (suite *SubscriberJourneyTestSuite) getSubscription(c *gin.Context) {
var subscription repository.RatePlanSubscription
if err := suite.db.First(&subscription, "id = ?", c.Param("id")).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "subscription not found"})
return
}
c.JSON(http.StatusOK, subscription)
}
func (suite *SubscriberJourneyTestSuite) cancelSubscription(c *gin.Context) {
if err := suite.db.Model(&repository.RatePlanSubscription{}).Where("id = ?", c.Param("id")).Updates(map[string]interface{}{
"status": "cancelled",
"ended_at": time.Now(),
"updated_at": time.Now(),
}).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "cancelled"})
}
func (suite *SubscriberJourneyTestSuite) recordUsage(c *gin.Context) {
var usage repository.RatePlanUsage
if err := c.ShouldBindJSON(&usage); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
usage.ID = fmt.Sprintf("usage-%d", time.Now().UnixNano())
usage.RatePlanID = "test-plan"
usage.LastUpdated = time.Now()
if err := suite.db.Create(&usage).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, usage)
}
func (suite *SubscriberJourneyTestSuite) getUsage(c *gin.Context) {
var usage []repository.RatePlanUsage
if err := suite.db.Where("rate_plan_id = ?", "test-plan").Find(&usage).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, usage)
}
func (suite *SubscriberJourneyTestSuite) processCharge(c *gin.Context) {
var charge map[string]interface{}
if err := c.ShouldBindJSON(&charge); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
charge["id"] = fmt.Sprintf("charge-%d", time.Now().UnixNano())
charge["status"] = "completed"
charge["processed_at"] = time.Now()
c.JSON(http.StatusOK, charge)
}
func (suite *SubscriberJourneyTestSuite) getInvoice(c *gin.Context) {
invoice := map[string]interface{}{
"subscription_id": c.Param("subscription_id"),
"total_amount": 29.99,
"currency": "USD",
"status": "paid",
"issued_at": time.Now(),
}
c.JSON(http.StatusOK, invoice)
}
func (suite *SubscriberJourneyTestSuite) getDashboard(c *gin.Context) {
dashboard := map[string]interface{}{
"total_subscribers": int64(100),
"active_subscriptions": int64(95),
"monthly_revenue": 2999.0,
"churn_rate": 0.05,
"generated_at": time.Now(),
}
c.JSON(http.StatusOK, dashboard)
}
func (suite *SubscriberJourneyTestSuite) getRevenue(c *gin.Context) {
revenue := map[string]interface{}{
"total_revenue": 50000.0,
"monthly_revenue": 5000.0,
"revenue_by_plan": map[string]float64{
"basic": 1500.0,
"premium": 3500.0,
},
"currency": "USD",
}
c.JSON(http.StatusOK, revenue)
}
// TearDownSuite cleans up the test suite
func (suite *SubscriberJourneyTestSuite) TearDownSuite() {
sqlDB, err := suite.db.DB()
if err == nil {
sqlDB.Close()
}
}
// TestSubscriberJourneySuite runs the E2E test suite
func TestSubscriberJourneySuite(t *testing.T) {
suite.Run(t, new(SubscriberJourneyTestSuite))
}