package services import ( "context" "fmt" "time" "github.com/sirupsen/logrus" "github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency" "github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/rateplan" ) // GetPlansInCurrency gets rate plans with prices converted to a specific currency func (rpci *RatePlanCurrencyIntegrator) GetPlansInCurrency(ctx context.Context, filter *rateplan.RatePlanFilter, targetCurrency string) ([]*rateplan.RatePlan, error) { // Get plans using original filter plans, err := rpci.ratePlanService.ListRatePlans(ctx, filter) if err != nil { return nil, fmt.Errorf("failed to get rate plans: %w", err) } // Convert prices to target currency for _, plan := range plans { if plan.Currency != targetCurrency { conversionReq := ¤cy.CurrencyConversionRequest{ Amount: plan.BasePrice, FromCurrency: plan.Currency, ToCurrency: targetCurrency, } conversion, err := rpci.billingService.ConvertAmount(ctx, conversionReq) if err != nil { rpci.logger.WithError(err).WithFields(logrus.Fields{ "plan_id": plan.ID, "from_currency": plan.Currency, "to_currency": targetCurrency, }).Warn("Failed to convert plan price") continue } // Store original price and update with converted price if plan.Metadata == nil { plan.Metadata = make(map[string]any) } plan.Metadata["original_price"] = plan.BasePrice plan.Metadata["original_currency"] = plan.Currency plan.Metadata["exchange_rate"] = conversion.ExchangeRate plan.BasePrice = conversion.ConvertedAmount plan.Currency = targetCurrency } } return plans, nil } // UpdatePlanCurrency updates a rate plan's currency and converts prices func (rpci *RatePlanCurrencyIntegrator) UpdatePlanCurrency(ctx context.Context, planID string, newCurrency string) error { // Get the current plan plan, err := rpci.ratePlanService.GetRatePlan(ctx, planID) if err != nil { return fmt.Errorf("failed to get rate plan: %w", err) } // If currency is the same, no conversion needed if plan.Currency == newCurrency { return nil } // Convert all monetary values to new currency convertedPrice, err := rpci.billingService.ConvertAmount(ctx, ¤cy.CurrencyConversionRequest{ Amount: plan.BasePrice, FromCurrency: plan.Currency, ToCurrency: newCurrency, }) if err != nil { return fmt.Errorf("failed to convert base price: %w", err) } // Update plan with new currency and converted prices plan.BasePrice = convertedPrice.ConvertedAmount plan.Currency = newCurrency // Store conversion information in metadata if plan.Metadata == nil { plan.Metadata = make(map[string]any) } plan.Metadata["currency_conversion"] = map[string]any{ "from_currency": plan.Metadata["original_currency"], "to_currency": newCurrency, "exchange_rate": convertedPrice.ExchangeRate, "converted_at": time.Now(), } // Update the plan updatedPlan, err := rpci.ratePlanService.UpdateRatePlan(ctx, plan) if err != nil { return fmt.Errorf("failed to update rate plan: %w", err) } // Use the updated plan for logging plan = updatedPlan rpci.logger.WithFields(logrus.Fields{ "plan_id": planID, "from_currency": plan.Metadata["original_currency"], "to_currency": newCurrency, "exchange_rate": convertedPrice.ExchangeRate, }).Info("Rate plan currency updated") return nil } // GetCurrencyUsageForPlan gets currency usage statistics for a specific rate plan func (rpci *RatePlanCurrencyIntegrator) GetCurrencyUsageForPlan(ctx context.Context, planID string) (map[string]int64, error) { // Get all subscriptions for this plan filter := &rateplan.SubscriptionFilter{ RatePlanID: planID, Status: rateplan.SubscriptionStatusActive, } subscriptions, err := rpci.ratePlanService.ListSubscriptions(ctx, "", filter) if err != nil { return nil, fmt.Errorf("failed to get subscriptions: %w", err) } // Count currencies currencyUsage := make(map[string]int64) for _, subscription := range subscriptions { currency := rpci.baseCurrency // Default to base currency if subscription.Metadata != nil { if subCurrency, exists := subscription.Metadata["subscription_currency"]; exists { if subCurrencyStr, ok := subCurrency.(string); ok { currency = subCurrencyStr } } } currencyUsage[currency]++ } return currencyUsage, nil }