mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-31 00:52:16 +00:00
* 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
192 lines
4.8 KiB
Go
192 lines
4.8 KiB
Go
package rateplan
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type PricingEngine struct {
|
|
repo Repository
|
|
logger Logger
|
|
}
|
|
|
|
type Logger interface {
|
|
WithError(err error) Logger
|
|
WithField(key string, value any) Logger
|
|
Error(msg string)
|
|
Info(msg string)
|
|
Warning(msg string)
|
|
}
|
|
|
|
func NewPricingEngine(repo Repository, logger Logger) *PricingEngine {
|
|
return &PricingEngine{
|
|
repo: repo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (pe *PricingEngine) ValidateRatePlan(ctx context.Context, plan *RatePlan) error {
|
|
if err := pe.validateBasicFields(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := pe.validateDates(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := pe.validateAllowances(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := pe.validateOverageRates(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := pe.validateDiscounts(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := pe.validateEarlyTermination(plan); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (pe *PricingEngine) CalculateOptimalPrice(ctx context.Context, plan *RatePlan) (*PriceOptimization, error) {
|
|
filter := &RatePlanFilter{
|
|
Region: plan.Region,
|
|
PlanType: plan.PlanType,
|
|
Status: PlanStatusActive,
|
|
IsActive: &[]bool{true}[0],
|
|
Limit: 10,
|
|
}
|
|
|
|
similarPlans, err := pe.repo.ListRatePlans(ctx, filter)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get similar plans: %w", err)
|
|
}
|
|
|
|
var totalBasePrice float64
|
|
for _, similarPlan := range similarPlans {
|
|
totalBasePrice += similarPlan.BasePrice
|
|
}
|
|
|
|
var marketAverage float64
|
|
if len(similarPlans) > 0 {
|
|
marketAverage = totalBasePrice / float64(len(similarPlans))
|
|
}
|
|
|
|
recommendedPrice := pe.calculateRecommendedPrice(plan, marketAverage)
|
|
|
|
optimization := &PriceOptimization{
|
|
CurrentPrice: plan.BasePrice,
|
|
MarketAverage: marketAverage,
|
|
RecommendedPrice: recommendedPrice,
|
|
PriceDifference: recommendedPrice - plan.BasePrice,
|
|
CompetitorCount: len(similarPlans),
|
|
OptimizedAt: time.Now(),
|
|
}
|
|
|
|
return optimization, nil
|
|
}
|
|
|
|
func (pe *PricingEngine) ValidateSubscription(ctx context.Context, req *SubscribeRequest) error {
|
|
plan, err := pe.repo.GetRatePlan(ctx, req.RatePlanID)
|
|
if err != nil {
|
|
return fmt.Errorf("rate plan not found: %w", err)
|
|
}
|
|
|
|
if !plan.IsActive || plan.Status != PlanStatusActive {
|
|
return fmt.Errorf("rate plan is not available for subscription")
|
|
}
|
|
|
|
now := time.Now()
|
|
if now.Before(plan.ValidFrom) {
|
|
return fmt.Errorf("rate plan is not yet available")
|
|
}
|
|
|
|
if plan.ValidTo != nil && now.After(*plan.ValidTo) {
|
|
return fmt.Errorf("rate plan has expired")
|
|
}
|
|
|
|
if len(req.AppliedDiscounts) > 0 {
|
|
if err := pe.validateSubscriptionDiscounts(plan, req.AppliedDiscounts); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (pe *PricingEngine) CalculateSubscriptionCost(ctx context.Context, req *CalculateCostRequest) (*CostBreakdown, error) {
|
|
// Get the rate plan
|
|
plan, err := pe.repo.GetRatePlan(ctx, req.RatePlanID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("rate plan not found: %w", err)
|
|
}
|
|
|
|
breakdown := &CostBreakdown{
|
|
RatePlanID: req.RatePlanID,
|
|
Currency: plan.Currency,
|
|
CalculatedAt: time.Now(),
|
|
BreakdownItems: []CostItem{},
|
|
}
|
|
|
|
baseCost := plan.BasePrice
|
|
breakdown.BreakdownItems = append(breakdown.BreakdownItems, CostItem{
|
|
Type: "base_price",
|
|
Description: "Base subscription cost",
|
|
Amount: baseCost,
|
|
Currency: plan.Currency,
|
|
})
|
|
|
|
dataOverageCost := pe.calculateDataOverage(plan, req.DataUsed)
|
|
if dataOverageCost > 0 {
|
|
breakdown.BreakdownItems = append(breakdown.BreakdownItems, CostItem{
|
|
Type: "data_overage",
|
|
Description: "Data usage over allowance",
|
|
Amount: dataOverageCost,
|
|
Currency: plan.Currency,
|
|
})
|
|
}
|
|
|
|
voiceOverageCost := pe.calculateVoiceOverage(plan, req.VoiceUsed)
|
|
if voiceOverageCost > 0 {
|
|
breakdown.BreakdownItems = append(breakdown.BreakdownItems, CostItem{
|
|
Type: "voice_overage",
|
|
Description: "Voice usage over allowance",
|
|
Amount: voiceOverageCost,
|
|
Currency: plan.Currency,
|
|
})
|
|
}
|
|
|
|
smsOverageCost := pe.calculateSMSOverage(plan, req.SMSUsed)
|
|
if smsOverageCost > 0 {
|
|
breakdown.BreakdownItems = append(breakdown.BreakdownItems, CostItem{
|
|
Type: "sms_overage",
|
|
Description: "SMS usage over allowance",
|
|
Amount: smsOverageCost,
|
|
Currency: plan.Currency,
|
|
})
|
|
}
|
|
|
|
discountAmount := pe.calculateDiscounts(plan, req.AppliedDiscounts, baseCost)
|
|
if discountAmount > 0 {
|
|
breakdown.BreakdownItems = append(breakdown.BreakdownItems, CostItem{
|
|
Type: "discount",
|
|
Description: "Applied discounts",
|
|
Amount: -discountAmount,
|
|
Currency: plan.Currency,
|
|
})
|
|
}
|
|
totalCost := baseCost + dataOverageCost + voiceOverageCost + smsOverageCost - discountAmount
|
|
breakdown.TotalCost = totalCost
|
|
breakdown.Subtotal = baseCost + dataOverageCost + voiceOverageCost + smsOverageCost
|
|
breakdown.DiscountTotal = discountAmount
|
|
|
|
return breakdown, nil
|
|
}
|
|
|