mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 11:02:54 +00:00
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
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/rateplan"
|
||||
)
|
||||
|
||||
@@ -21,7 +22,12 @@ func (rpci *RatePlanCurrencyIntegrator) GetPlansInCurrency(ctx context.Context,
|
||||
// Convert prices to target currency
|
||||
for _, plan := range plans {
|
||||
if plan.Currency != targetCurrency {
|
||||
conversion, err := rpci.exchangeService.ConvertAmount(ctx, plan.BasePrice, 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,
|
||||
@@ -60,7 +66,11 @@ func (rpci *RatePlanCurrencyIntegrator) UpdatePlanCurrency(ctx context.Context,
|
||||
}
|
||||
|
||||
// Convert all monetary values to new currency
|
||||
convertedPrice, err := rpci.exchangeService.ConvertAmount(ctx, plan.BasePrice, plan.Currency, newCurrency)
|
||||
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)
|
||||
}
|
||||
@@ -99,37 +109,6 @@ func (rpci *RatePlanCurrencyIntegrator) UpdatePlanCurrency(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
// calculateOverageCost calculates overage costs for usage
|
||||
func (rpci *RatePlanCurrencyIntegrator) calculateOverageCost(ctx context.Context, plan *rateplan.RatePlan, usage *rateplan.RatePlanUsage) (float64, error) {
|
||||
overageCost := 0.0
|
||||
|
||||
// Calculate data overage
|
||||
if plan.DataAllowance != nil && usage.DataUsed > plan.DataAllowance.Amount {
|
||||
dataOverage := usage.DataUsed - plan.DataAllowance.Amount
|
||||
if plan.OverageRates != nil {
|
||||
overageCost += float64(dataOverage) * plan.OverageRates.DataRate
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate voice overage
|
||||
if plan.VoiceAllowance != nil && usage.VoiceUsed > plan.VoiceAllowance.Minutes {
|
||||
voiceOverage := usage.VoiceUsed - plan.VoiceAllowance.Minutes
|
||||
if plan.OverageRates != nil {
|
||||
overageCost += float64(voiceOverage) * plan.OverageRates.VoiceRate
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate SMS overage
|
||||
if plan.SMSAllowance != nil && usage.SMSUsed > plan.SMSAllowance.Messages {
|
||||
smsOverage := usage.SMSUsed - plan.SMSAllowance.Messages
|
||||
if plan.OverageRates != nil {
|
||||
overageCost += float64(smsOverage) * plan.OverageRates.SMSRate
|
||||
}
|
||||
}
|
||||
|
||||
return overageCost, 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
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *TenantServiceImpl) CreateTenant(ctx context.Context, req *tenant.Create
|
||||
}
|
||||
|
||||
// Create tenant
|
||||
tenant := &tenant.Tenant{
|
||||
newTenant := &tenant.Tenant{
|
||||
ID: uuid.New().String(),
|
||||
Name: req.Name,
|
||||
Domain: req.Domain,
|
||||
@@ -61,21 +61,21 @@ func (s *TenantServiceImpl) CreateTenant(ctx context.Context, req *tenant.Create
|
||||
}
|
||||
|
||||
// Set default settings if not provided
|
||||
if tenant.Settings == nil {
|
||||
tenant.Settings = s.getDefaultSettings(req.Plan)
|
||||
if newTenant.Settings == nil {
|
||||
newTenant.Settings = s.getDefaultSettings(req.Plan)
|
||||
}
|
||||
|
||||
// Save tenant
|
||||
if err := s.repository.CreateTenant(ctx, tenant); err != nil {
|
||||
if err := s.repository.CreateTenant(ctx, newTenant); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to create tenant")
|
||||
return nil, fmt.Errorf("failed to create tenant: %w", err)
|
||||
}
|
||||
|
||||
// Create initial configuration
|
||||
config := &tenant.TenantConfig{
|
||||
TenantID: tenant.ID,
|
||||
TenantID: newTenant.ID,
|
||||
Config: make(map[string]interface{}),
|
||||
Settings: tenant.Settings,
|
||||
Settings: newTenant.Settings,
|
||||
Quotas: s.getDefaultQuotas(req.Plan),
|
||||
Features: s.getDefaultFeatures(req.Plan),
|
||||
}
|
||||
@@ -85,12 +85,12 @@ func (s *TenantServiceImpl) CreateTenant(ctx context.Context, req *tenant.Create
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": tenant.ID,
|
||||
"name": tenant.Name,
|
||||
"domain": tenant.Domain,
|
||||
"tenant_id": newTenant.ID,
|
||||
"name": newTenant.Name,
|
||||
"domain": newTenant.Domain,
|
||||
}).Info("Tenant created successfully")
|
||||
|
||||
return tenant, nil
|
||||
return newTenant, nil
|
||||
}
|
||||
|
||||
// GetTenant retrieves a tenant by ID
|
||||
|
||||
@@ -3,191 +3,10 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/tenant"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AddUserToTenant adds a user to a tenant
|
||||
func (s *TenantServiceImpl) AddUserToTenant(ctx context.Context, req *tenant.CreateTenantUserRequest) (*tenant.TenantUser, error) {
|
||||
// Validate request
|
||||
if err := s.validateCreateTenantUserRequest(req); err != nil {
|
||||
return nil, fmt.Errorf("validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
existing, err := s.repository.GetTenantUser(ctx, req.TenantID, req.UserID)
|
||||
if err == nil && existing != nil {
|
||||
return nil, errors.New("user already exists in tenant")
|
||||
}
|
||||
|
||||
// Create tenant user
|
||||
tenantUser := &tenant.TenantUser{
|
||||
ID: uuid.New().String(),
|
||||
TenantID: req.TenantID,
|
||||
UserID: req.UserID,
|
||||
Email: req.Email,
|
||||
Role: req.Role,
|
||||
Status: tenant.TenantUserStatusActive,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Save tenant user
|
||||
if err := s.repository.CreateTenantUser(ctx, tenantUser); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to create tenant user")
|
||||
return nil, fmt.Errorf("failed to add user to tenant: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": req.TenantID,
|
||||
"user_id": req.UserID,
|
||||
"role": req.Role,
|
||||
}).Info("User added to tenant successfully")
|
||||
|
||||
return tenantUser, nil
|
||||
}
|
||||
|
||||
// GetTenantUser retrieves a tenant user
|
||||
func (s *TenantServiceImpl) GetTenantUser(ctx context.Context, tenantID, userID string) (*tenant.TenantUser, error) {
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
s.logger.WithError(err).WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Error("Failed to get tenant user")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// UpdateTenantUser updates a tenant user
|
||||
func (s *TenantServiceImpl) UpdateTenantUser(ctx context.Context, tenantID, userID string, req *tenant.UpdateTenantUserRequest) (*tenant.TenantUser, error) {
|
||||
// Get existing user
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
if req.Role != nil {
|
||||
user.Role = *req.Role
|
||||
}
|
||||
if req.Status != nil {
|
||||
user.Status = *req.Status
|
||||
}
|
||||
|
||||
user.UpdatedAt = time.Now()
|
||||
|
||||
// Save user
|
||||
if err := s.repository.UpdateTenantUser(ctx, user); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to update tenant user")
|
||||
return nil, fmt.Errorf("failed to update tenant user: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Info("Tenant user updated successfully")
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// RemoveUserFromTenant removes a user from a tenant
|
||||
func (s *TenantServiceImpl) RemoveUserFromTenant(ctx context.Context, tenantID, userID string) error {
|
||||
// Delete tenant user
|
||||
if err := s.repository.DeleteTenantUser(ctx, tenantID, userID); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to remove user from tenant")
|
||||
return fmt.Errorf("failed to remove user from tenant: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Info("User removed from tenant successfully")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTenantUsers lists tenant users with filtering
|
||||
func (s *TenantServiceImpl) ListTenantUsers(ctx context.Context, filter *tenant.TenantUserFilter) ([]*tenant.TenantUser, error) {
|
||||
users, err := s.repository.ListTenantUsers(ctx, filter)
|
||||
if err != nil {
|
||||
s.logger.WithError(err).Error("Failed to list tenant users")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// ValidateTenantAccess validates tenant access
|
||||
func (s *TenantServiceImpl) ValidateTenantAccess(ctx context.Context, tenantID, userID string) (*tenant.TenantContext, error) {
|
||||
// Get tenant
|
||||
tenant, err := s.repository.GetTenant(ctx, tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenant not found: %w", err)
|
||||
}
|
||||
|
||||
// Check tenant status
|
||||
if tenant.Status != "active" {
|
||||
return nil, fmt.Errorf("tenant is not active")
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("user not found in tenant: %w", err)
|
||||
}
|
||||
|
||||
// Check user status
|
||||
if user.Status != "active" {
|
||||
return nil, fmt.Errorf("user is not active")
|
||||
}
|
||||
|
||||
// Create context
|
||||
context := &tenant.TenantContext{
|
||||
TenantID: tenantID,
|
||||
UserID: userID,
|
||||
Tenant: tenant,
|
||||
User: user,
|
||||
Roles: []string{string(user.Role)},
|
||||
Permissions: []string{},
|
||||
Settings: tenant.Settings,
|
||||
Quotas: []tenant.ResourceQuota{},
|
||||
Features: map[string]bool{},
|
||||
}
|
||||
|
||||
return context, nil
|
||||
}
|
||||
|
||||
// GetTenantContext retrieves tenant context
|
||||
func (s *TenantServiceImpl) GetTenantContext(ctx context.Context, tenantID string) (*tenant.TenantContext, error) {
|
||||
// Get tenant
|
||||
tenant, err := s.repository.GetTenant(ctx, tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenant not found: %w", err)
|
||||
}
|
||||
|
||||
// Create context with basic tenant info
|
||||
context := &tenant.TenantContext{
|
||||
TenantID: tenantID,
|
||||
UserID: "",
|
||||
Tenant: tenant,
|
||||
User: nil,
|
||||
Roles: []string{},
|
||||
Permissions: []string{},
|
||||
Settings: tenant.Settings,
|
||||
Quotas: []tenant.ResourceQuota{},
|
||||
Features: map[string]bool{},
|
||||
}
|
||||
|
||||
return context, nil
|
||||
}
|
||||
|
||||
// HasPermission checks if user has permission
|
||||
func (s *TenantServiceImpl) HasPermission(ctx context.Context, tenantID, userID, permission string) (bool, error) {
|
||||
// Get tenant user
|
||||
@@ -209,7 +28,6 @@ func (s *TenantServiceImpl) HasPermission(ctx context.Context, tenantID, userID,
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
func (s *TenantServiceImpl) validateCreateTenantUserRequest(req *tenant.CreateTenantUserRequest) error {
|
||||
if req.TenantID == "" {
|
||||
return errors.New("tenant ID is required")
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/tenant"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AddUserToTenant adds a user to a tenant
|
||||
func (s *TenantServiceImpl) AddUserToTenant(ctx context.Context, req *tenant.CreateTenantUserRequest) (*tenant.TenantUser, error) {
|
||||
// Validate request
|
||||
if err := s.validateCreateTenantUserRequest(req); err != nil {
|
||||
return nil, fmt.Errorf("validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
existing, err := s.repository.GetTenantUser(ctx, req.TenantID, req.UserID)
|
||||
if err == nil && existing != nil {
|
||||
return nil, errors.New("user already exists in tenant")
|
||||
}
|
||||
|
||||
// Create tenant user
|
||||
tenantUser := &tenant.TenantUser{
|
||||
ID: uuid.New().String(),
|
||||
TenantID: req.TenantID,
|
||||
UserID: req.UserID,
|
||||
Email: req.Email,
|
||||
Role: req.Role,
|
||||
Status: tenant.TenantUserStatusActive,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Save tenant user
|
||||
if err := s.repository.CreateTenantUser(ctx, tenantUser); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to create tenant user")
|
||||
return nil, fmt.Errorf("failed to add user to tenant: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": req.TenantID,
|
||||
"user_id": req.UserID,
|
||||
"role": req.Role,
|
||||
}).Info("User added to tenant successfully")
|
||||
|
||||
return tenantUser, nil
|
||||
}
|
||||
|
||||
// GetTenantUser retrieves a tenant user
|
||||
func (s *TenantServiceImpl) GetTenantUser(ctx context.Context, tenantID, userID string) (*tenant.TenantUser, error) {
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
s.logger.WithError(err).WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Error("Failed to get tenant user")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// UpdateTenantUser updates a tenant user
|
||||
func (s *TenantServiceImpl) UpdateTenantUser(ctx context.Context, tenantID, userID string, req *tenant.UpdateTenantUserRequest) (*tenant.TenantUser, error) {
|
||||
// Get existing user
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
if req.Role != nil {
|
||||
user.Role = *req.Role
|
||||
}
|
||||
if req.Status != nil {
|
||||
user.Status = *req.Status
|
||||
}
|
||||
|
||||
user.UpdatedAt = time.Now()
|
||||
|
||||
// Save user
|
||||
if err := s.repository.UpdateTenantUser(ctx, user); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to update tenant user")
|
||||
return nil, fmt.Errorf("failed to update tenant user: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Info("Tenant user updated successfully")
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// RemoveUserFromTenant removes a user from a tenant
|
||||
func (s *TenantServiceImpl) RemoveUserFromTenant(ctx context.Context, tenantID, userID string) error {
|
||||
// Delete tenant user
|
||||
if err := s.repository.DeleteTenantUser(ctx, tenantID, userID); err != nil {
|
||||
s.logger.WithError(err).Error("Failed to remove user from tenant")
|
||||
return fmt.Errorf("failed to remove user from tenant: %w", err)
|
||||
}
|
||||
|
||||
s.logger.WithFields(logrus.Fields{
|
||||
"tenant_id": tenantID,
|
||||
"user_id": userID,
|
||||
}).Info("User removed from tenant successfully")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTenantUsers lists tenant users with filtering
|
||||
func (s *TenantServiceImpl) ListTenantUsers(ctx context.Context, filter *tenant.TenantUserFilter) ([]*tenant.TenantUser, error) {
|
||||
users, err := s.repository.ListTenantUsers(ctx, filter)
|
||||
if err != nil {
|
||||
s.logger.WithError(err).Error("Failed to list tenant users")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// ValidateTenantAccess validates tenant access
|
||||
func (s *TenantServiceImpl) ValidateTenantAccess(ctx context.Context, tenantID, userID string) (*tenant.TenantContext, error) {
|
||||
// Get tenant
|
||||
tenantRecord, err := s.repository.GetTenant(ctx, tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenant not found: %w", err)
|
||||
}
|
||||
|
||||
// Check tenant status
|
||||
if tenantRecord.Status != "active" {
|
||||
return nil, fmt.Errorf("tenant is not active")
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := s.repository.GetTenantUser(ctx, tenantID, userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("user not found in tenant: %w", err)
|
||||
}
|
||||
|
||||
// Check user status
|
||||
if user.Status != "active" {
|
||||
return nil, fmt.Errorf("user is not active")
|
||||
}
|
||||
|
||||
// Create context
|
||||
tenantCtx := &tenant.TenantContext{
|
||||
TenantID: tenantID,
|
||||
TenantName: tenantRecord.Name,
|
||||
Plan: tenantRecord.Plan,
|
||||
UserID: userID,
|
||||
UserRole: user.Role,
|
||||
Settings: tenantRecord.Settings,
|
||||
Metadata: tenantRecord.Metadata,
|
||||
}
|
||||
|
||||
return tenantCtx, nil
|
||||
}
|
||||
|
||||
// GetTenantContext retrieves tenant context
|
||||
func (s *TenantServiceImpl) GetTenantContext(ctx context.Context, tenantID string) (*tenant.TenantContext, error) {
|
||||
// Get tenant
|
||||
tenantRecord, err := s.repository.GetTenant(ctx, tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenant not found: %w", err)
|
||||
}
|
||||
|
||||
// Create context with basic tenant info
|
||||
tenantCtx := &tenant.TenantContext{
|
||||
TenantID: tenantID,
|
||||
TenantName: tenantRecord.Name,
|
||||
Plan: tenantRecord.Plan,
|
||||
UserID: "",
|
||||
Settings: tenantRecord.Settings,
|
||||
Metadata: tenantRecord.Metadata,
|
||||
}
|
||||
|
||||
return tenantCtx, nil
|
||||
}
|
||||
Reference in New Issue
Block a user