mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-31 09:02:15 +00:00
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
This commit is contained in:
@@ -8,15 +8,15 @@ import (
|
|||||||
|
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/handlers"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/handlers"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/service"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/services"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SelectionIntegration struct {
|
type SelectionIntegration struct {
|
||||||
manager *smdp.SMDPManager
|
manager *smdp.SMDPManager
|
||||||
selectionService *service.SelectionService
|
selectionService *services.SelectionService
|
||||||
selectionHandler *handlers.SelectionHandler
|
selectionHandler *handlers.SelectionHandler
|
||||||
smdpService *service.SMDPService
|
smdpService *services.SMDPService
|
||||||
server *http.Server
|
server *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +33,10 @@ func NewSelectionIntegration(repo *repository.PostgresProfileStore) *SelectionIn
|
|||||||
manager := smdp.NewSMDPManager(repo, config)
|
manager := smdp.NewSMDPManager(repo, config)
|
||||||
|
|
||||||
// Create selection service
|
// Create selection service
|
||||||
selectionService := service.NewSelectionService(manager)
|
selectionService := services.NewSelectionService(manager)
|
||||||
|
|
||||||
// Create SMDP service
|
// Create SMDP service
|
||||||
smdpService := service.NewSMDPService(repo)
|
smdpService := services.NewSMDPService(repo)
|
||||||
|
|
||||||
return &SelectionIntegration{
|
return &SelectionIntegration{
|
||||||
manager: manager,
|
manager: manager,
|
||||||
@@ -85,7 +85,7 @@ func (si *SelectionIntegration) GetManager() *smdp.SMDPManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetSelectionService returns the selection service for testing
|
// GetSelectionService returns the selection service for testing
|
||||||
func (si *SelectionIntegration) GetSelectionService() *service.SelectionService {
|
func (si *SelectionIntegration) GetSelectionService() *services.SelectionService {
|
||||||
return si.selectionService
|
return si.selectionService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/handlers"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/handlers"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/repository"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/service"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/services"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/smdp"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SMDPIntegration integrates the multi-carrier SM-DP+ system with the existing carrier connector
|
// SMDPIntegration integrates the multi-carrier SM-DP+ system with the existing carrier connector
|
||||||
type SMDPIntegration struct {
|
type SMDPIntegration struct {
|
||||||
service *service.SMDPService
|
service *services.SMDPService
|
||||||
handler *handlers.SMDPHandler
|
handler *handlers.SMDPHandler
|
||||||
repository *repository.PostgresProfileStore
|
repository *repository.PostgresProfileStore
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
@@ -24,7 +24,7 @@ func NewSMDPIntegration(repo *repository.PostgresProfileStore) *SMDPIntegration
|
|||||||
logger := logrus.New()
|
logger := logrus.New()
|
||||||
logger.SetLevel(logrus.InfoLevel)
|
logger.SetLevel(logrus.InfoLevel)
|
||||||
|
|
||||||
svc := service.NewSMDPService(repo)
|
svc := services.NewSMDPService(repo)
|
||||||
manager := svc.GetManager()
|
manager := svc.GetManager()
|
||||||
hnd := handlers.NewSMDPHandler(manager)
|
hnd := handlers.NewSMDPHandler(manager)
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ func (i *SMDPIntegration) metricsHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetService returns the SM-DP+ service for direct access
|
// GetService returns the SM-DP+ service for direct access
|
||||||
func (i *SMDPIntegration) GetService() *service.SMDPService {
|
func (i *SMDPIntegration) GetService() *services.SMDPService {
|
||||||
return i.service
|
return i.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -1,9 +1,10 @@
|
|||||||
package currency
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -23,7 +24,7 @@ func NewGormRepository(db *gorm.DB, logger *logrus.Logger) *GormRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateCurrency creates a new currency
|
// CreateCurrency creates a new currency
|
||||||
func (r *GormRepository) CreateCurrency(ctx context.Context, currency *Currency) error {
|
func (r *GormRepository) CreateCurrency(ctx context.Context, currency *currency.Currency) error {
|
||||||
model := r.currencyToModel(currency)
|
model := r.currencyToModel(currency)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
||||||
@@ -35,8 +36,8 @@ func (r *GormRepository) CreateCurrency(ctx context.Context, currency *Currency)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrency retrieves a currency by code
|
// GetCurrency retrieves a currency by code
|
||||||
func (r *GormRepository) GetCurrency(ctx context.Context, code string) (*Currency, error) {
|
func (r *GormRepository) GetCurrency(ctx context.Context, code string) (*currency.Currency, error) {
|
||||||
var model CurrencyModel
|
var model currency.CurrencyModel
|
||||||
if err := r.db.WithContext(ctx).Where("code = ?", code).First(&model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Where("code = ?", code).First(&model).Error; err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
return nil, fmt.Errorf("currency not found: %s", code)
|
return nil, fmt.Errorf("currency not found: %s", code)
|
||||||
@@ -49,7 +50,7 @@ func (r *GormRepository) GetCurrency(ctx context.Context, code string) (*Currenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCurrency updates an existing currency
|
// UpdateCurrency updates an existing currency
|
||||||
func (r *GormRepository) UpdateCurrency(ctx context.Context, currency *Currency) error {
|
func (r *GormRepository) UpdateCurrency(ctx context.Context, currency *currency.Currency) error {
|
||||||
model := r.currencyToModel(currency)
|
model := r.currencyToModel(currency)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
||||||
@@ -62,7 +63,7 @@ func (r *GormRepository) UpdateCurrency(ctx context.Context, currency *Currency)
|
|||||||
|
|
||||||
// DeleteCurrency deletes a currency
|
// DeleteCurrency deletes a currency
|
||||||
func (r *GormRepository) DeleteCurrency(ctx context.Context, code string) error {
|
func (r *GormRepository) DeleteCurrency(ctx context.Context, code string) error {
|
||||||
if err := r.db.WithContext(ctx).Delete(&CurrencyModel{}, "code = ?", code).Error; err != nil {
|
if err := r.db.WithContext(ctx).Delete(¤cy.CurrencyModel{}, "code = ?", code).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to delete currency")
|
r.logger.WithError(err).Error("Failed to delete currency")
|
||||||
return fmt.Errorf("failed to delete currency: %w", err)
|
return fmt.Errorf("failed to delete currency: %w", err)
|
||||||
}
|
}
|
||||||
@@ -71,8 +72,8 @@ func (r *GormRepository) DeleteCurrency(ctx context.Context, code string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListCurrencies retrieves currencies based on filter
|
// ListCurrencies retrieves currencies based on filter
|
||||||
func (r *GormRepository) ListCurrencies(ctx context.Context, filter *CurrencyFilter) ([]*Currency, error) {
|
func (r *GormRepository) ListCurrencies(ctx context.Context, filter *currency.CurrencyFilter) ([]*currency.Currency, error) {
|
||||||
query := r.db.WithContext(ctx).Model(&CurrencyModel{})
|
query := r.db.WithContext(ctx).Model(¤cy.CurrencyModel{})
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if filter.IsActive != nil {
|
if filter.IsActive != nil {
|
||||||
@@ -101,13 +102,13 @@ func (r *GormRepository) ListCurrencies(ctx context.Context, filter *CurrencyFil
|
|||||||
query = query.Offset(filter.Offset)
|
query = query.Offset(filter.Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
var models []CurrencyModel
|
var models []currency.CurrencyModel
|
||||||
if err := query.Find(&models).Error; err != nil {
|
if err := query.Find(&models).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to list currencies")
|
r.logger.WithError(err).Error("Failed to list currencies")
|
||||||
return nil, fmt.Errorf("failed to list currencies: %w", err)
|
return nil, fmt.Errorf("failed to list currencies: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
currencies := make([]*Currency, 0, len(models))
|
currencies := make([]*currency.Currency, 0, len(models))
|
||||||
for _, model := range models {
|
for _, model := range models {
|
||||||
curr, err := r.modelToCurrency(&model)
|
curr, err := r.modelToCurrency(&model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,8 +122,8 @@ func (r *GormRepository) ListCurrencies(ctx context.Context, filter *CurrencyFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountCurrencies counts currencies based on filter
|
// CountCurrencies counts currencies based on filter
|
||||||
func (r *GormRepository) CountCurrencies(ctx context.Context, filter *CurrencyFilter) (int, error) {
|
func (r *GormRepository) CountCurrencies(ctx context.Context, filter *currency.CurrencyFilter) (int, error) {
|
||||||
query := r.db.WithContext(ctx).Model(&CurrencyModel{})
|
query := r.db.WithContext(ctx).Model(¤cy.CurrencyModel{})
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if filter.IsActive != nil {
|
if filter.IsActive != nil {
|
||||||
@@ -142,7 +143,7 @@ func (r *GormRepository) CountCurrencies(ctx context.Context, filter *CurrencyFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateExchangeRate creates a new exchange rate
|
// CreateExchangeRate creates a new exchange rate
|
||||||
func (r *GormRepository) CreateExchangeRate(ctx context.Context, rate *ExchangeRate) error {
|
func (r *GormRepository) CreateExchangeRate(ctx context.Context, rate *currency.ExchangeRate) error {
|
||||||
model := r.exchangeRateToModel(rate)
|
model := r.exchangeRateToModel(rate)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
||||||
@@ -154,8 +155,8 @@ func (r *GormRepository) CreateExchangeRate(ctx context.Context, rate *ExchangeR
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetExchangeRate retrieves an exchange rate by ID
|
// GetExchangeRate retrieves an exchange rate by ID
|
||||||
func (r *GormRepository) GetExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*ExchangeRate, error) {
|
func (r *GormRepository) GetExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*currency.ExchangeRate, error) {
|
||||||
var model ExchangeRateModel
|
var model currency.ExchangeRateModel
|
||||||
if err := r.db.WithContext(ctx).Where("from_currency = ? AND to_currency = ?", fromCurrency, toCurrency).First(&model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Where("from_currency = ? AND to_currency = ?", fromCurrency, toCurrency).First(&model).Error; err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
return nil, fmt.Errorf("exchange rate not found: %s to %s", fromCurrency, toCurrency)
|
return nil, fmt.Errorf("exchange rate not found: %s to %s", fromCurrency, toCurrency)
|
||||||
@@ -168,7 +169,7 @@ func (r *GormRepository) GetExchangeRate(ctx context.Context, fromCurrency, toCu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateExchangeRate updates an existing exchange rate
|
// UpdateExchangeRate updates an existing exchange rate
|
||||||
func (r *GormRepository) UpdateExchangeRate(ctx context.Context, rate *ExchangeRate) error {
|
func (r *GormRepository) UpdateExchangeRate(ctx context.Context, rate *currency.ExchangeRate) error {
|
||||||
model := r.exchangeRateToModel(rate)
|
model := r.exchangeRateToModel(rate)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
||||||
@@ -181,7 +182,7 @@ func (r *GormRepository) UpdateExchangeRate(ctx context.Context, rate *ExchangeR
|
|||||||
|
|
||||||
// DeleteExchangeRate deletes an exchange rate
|
// DeleteExchangeRate deletes an exchange rate
|
||||||
func (r *GormRepository) DeleteExchangeRate(ctx context.Context, id string) error {
|
func (r *GormRepository) DeleteExchangeRate(ctx context.Context, id string) error {
|
||||||
if err := r.db.WithContext(ctx).Delete(&ExchangeRateModel{}, "id = ?", id).Error; err != nil {
|
if err := r.db.WithContext(ctx).Delete(¤cy.ExchangeRateModel{}, "id = ?", id).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to delete exchange rate")
|
r.logger.WithError(err).Error("Failed to delete exchange rate")
|
||||||
return fmt.Errorf("failed to delete exchange rate: %w", err)
|
return fmt.Errorf("failed to delete exchange rate: %w", err)
|
||||||
}
|
}
|
||||||
+17
-15
@@ -1,14 +1,16 @@
|
|||||||
package currency
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
)
|
)
|
||||||
|
|
||||||
// currencyToModel converts currency domain model to database model
|
// currencyToModel converts currency domain model to database model
|
||||||
func (r *GormRepository) currencyToModel(currency *Currency) *CurrencyModel {
|
func (r *GormRepository) currencyToModel(currency *currency.Currency) *currency.CurrencyModel {
|
||||||
return &CurrencyModel{
|
return ¤cy.CurrencyModel{
|
||||||
Code: currency.Code,
|
Code: currency.Code,
|
||||||
Name: currency.Name,
|
Name: currency.Name,
|
||||||
Symbol: currency.Symbol,
|
Symbol: currency.Symbol,
|
||||||
@@ -21,13 +23,13 @@ func (r *GormRepository) currencyToModel(currency *Currency) *CurrencyModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// modelToCurrency converts database model to currency domain model
|
// modelToCurrency converts database model to currency domain model
|
||||||
func (r *GormRepository) modelToCurrency(model *CurrencyModel) (*Currency, error) {
|
func (r *GormRepository) modelToCurrency(model *currency.CurrencyModel) (*currency.Currency, error) {
|
||||||
var regions []string
|
var regions []string
|
||||||
if model.SupportedRegions != "" {
|
if model.SupportedRegions != "" {
|
||||||
regions = strings.Split(model.SupportedRegions, ",")
|
regions = strings.Split(model.SupportedRegions, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Currency{
|
return ¤cy.Currency{
|
||||||
Code: model.Code,
|
Code: model.Code,
|
||||||
Name: model.Name,
|
Name: model.Name,
|
||||||
Symbol: model.Symbol,
|
Symbol: model.Symbol,
|
||||||
@@ -40,8 +42,8 @@ func (r *GormRepository) modelToCurrency(model *CurrencyModel) (*Currency, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exchangeRateToModel converts exchange rate domain model to database model
|
// exchangeRateToModel converts exchange rate domain model to database model
|
||||||
func (r *GormRepository) exchangeRateToModel(rate *ExchangeRate) *ExchangeRateModel {
|
func (r *GormRepository) exchangeRateToModel(rate *currency.ExchangeRate) *currency.ExchangeRateModel {
|
||||||
return &ExchangeRateModel{
|
return ¤cy.ExchangeRateModel{
|
||||||
ID: rate.ID,
|
ID: rate.ID,
|
||||||
FromCurrency: rate.FromCurrency,
|
FromCurrency: rate.FromCurrency,
|
||||||
ToCurrency: rate.ToCurrency,
|
ToCurrency: rate.ToCurrency,
|
||||||
@@ -56,8 +58,8 @@ func (r *GormRepository) exchangeRateToModel(rate *ExchangeRate) *ExchangeRateMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// modelToExchangeRate converts database model to exchange rate domain model
|
// modelToExchangeRate converts database model to exchange rate domain model
|
||||||
func (r *GormRepository) modelToExchangeRate(model *ExchangeRateModel) (*ExchangeRate, error) {
|
func (r *GormRepository) modelToExchangeRate(model *currency.ExchangeRateModel) (*currency.ExchangeRate, error) {
|
||||||
return &ExchangeRate{
|
return ¤cy.ExchangeRate{
|
||||||
ID: model.ID,
|
ID: model.ID,
|
||||||
FromCurrency: model.FromCurrency,
|
FromCurrency: model.FromCurrency,
|
||||||
ToCurrency: model.ToCurrency,
|
ToCurrency: model.ToCurrency,
|
||||||
@@ -72,7 +74,7 @@ func (r *GormRepository) modelToExchangeRate(model *ExchangeRateModel) (*Exchang
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transactionToModel converts transaction domain model to database model
|
// transactionToModel converts transaction domain model to database model
|
||||||
func (r *GormRepository) transactionToModel(transaction *Transaction) *TransactionModel {
|
func (r *GormRepository) transactionToModel(transaction *currency.Transaction) *currency.TransactionModel {
|
||||||
metadata := ""
|
metadata := ""
|
||||||
if transaction.Metadata != nil {
|
if transaction.Metadata != nil {
|
||||||
if data, err := json.Marshal(transaction.Metadata); err == nil {
|
if data, err := json.Marshal(transaction.Metadata); err == nil {
|
||||||
@@ -80,7 +82,7 @@ func (r *GormRepository) transactionToModel(transaction *Transaction) *Transacti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &TransactionModel{
|
return ¤cy.TransactionModel{
|
||||||
ID: transaction.ID,
|
ID: transaction.ID,
|
||||||
ProfileID: transaction.ProfileID,
|
ProfileID: transaction.ProfileID,
|
||||||
SubscriptionID: transaction.SubscriptionID,
|
SubscriptionID: transaction.SubscriptionID,
|
||||||
@@ -99,7 +101,7 @@ func (r *GormRepository) transactionToModel(transaction *Transaction) *Transacti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// modelToTransaction converts database model to transaction domain model
|
// modelToTransaction converts database model to transaction domain model
|
||||||
func (r *GormRepository) modelToTransaction(model *TransactionModel) (*Transaction, error) {
|
func (r *GormRepository) modelToTransaction(model *currency.TransactionModel) (*currency.Transaction, error) {
|
||||||
var metadata map[string]interface{}
|
var metadata map[string]interface{}
|
||||||
if model.Metadata != "" {
|
if model.Metadata != "" {
|
||||||
if err := json.Unmarshal([]byte(model.Metadata), &metadata); err != nil {
|
if err := json.Unmarshal([]byte(model.Metadata), &metadata); err != nil {
|
||||||
@@ -107,18 +109,18 @@ func (r *GormRepository) modelToTransaction(model *TransactionModel) (*Transacti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Transaction{
|
return ¤cy.Transaction{
|
||||||
ID: model.ID,
|
ID: model.ID,
|
||||||
ProfileID: model.ProfileID,
|
ProfileID: model.ProfileID,
|
||||||
SubscriptionID: model.SubscriptionID,
|
SubscriptionID: model.SubscriptionID,
|
||||||
Type: TransactionType(model.Type),
|
Type: currency.TransactionType(model.Type),
|
||||||
Amount: model.Amount,
|
Amount: model.Amount,
|
||||||
Currency: model.Currency,
|
Currency: model.Currency,
|
||||||
BaseAmount: model.BaseAmount,
|
BaseAmount: model.BaseAmount,
|
||||||
BaseCurrency: model.BaseCurrency,
|
BaseCurrency: model.BaseCurrency,
|
||||||
ExchangeRate: model.ExchangeRate,
|
ExchangeRate: model.ExchangeRate,
|
||||||
Description: model.Description,
|
Description: model.Description,
|
||||||
Status: TransactionStatus(model.Status),
|
Status: currency.TransactionStatus(model.Status),
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
CreatedAt: model.CreatedAt,
|
CreatedAt: model.CreatedAt,
|
||||||
UpdatedAt: model.UpdatedAt,
|
UpdatedAt: model.UpdatedAt,
|
||||||
+1
-15
@@ -1,27 +1,13 @@
|
|||||||
package rateplan
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GormRepository implements the Repository interface using GORM
|
|
||||||
type GormRepository struct {
|
|
||||||
db *gorm.DB
|
|
||||||
logger *logrus.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGormRepository creates a new GORM repository
|
|
||||||
func NewGormRepository(db *gorm.DB, logger *logrus.Logger) *GormRepository {
|
|
||||||
return &GormRepository{
|
|
||||||
db: db,
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// CreateUsage creates a new usage record
|
// CreateUsage creates a new usage record
|
||||||
func (r *GormRepository) CreateUsage(ctx context.Context, usage *RatePlanUsage) error {
|
func (r *GormRepository) CreateUsage(ctx context.Context, usage *RatePlanUsage) error {
|
||||||
usage.LastUpdated = time.Now()
|
usage.LastUpdated = time.Now()
|
||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateRatePlan creates a new rate plan
|
// CreateRatePlan creates a new rate plan
|
||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateSubscription creates a new rate plan subscription
|
// CreateSubscription creates a new rate plan subscription
|
||||||
func (r *GormRepository) CreateSubscription(ctx context.Context, subscription *RatePlanSubscription) error {
|
func (r *GormRepository) CreateSubscription(ctx context.Context, subscription *RatePlanSubscription) error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -85,6 +86,7 @@ func (r *GormRepository) DeleteSubscription(ctx context.Context, id string) erro
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListSubscriptions retrieves subscriptions for a profile
|
// ListSubscriptions retrieves subscriptions for a profile
|
||||||
func (r *GormRepository) ListSubscriptions(ctx context.Context, profileID string, filter *SubscriptionFilter) ([]*RatePlanSubscription, error) {
|
func (r *GormRepository) ListSubscriptions(ctx context.Context, profileID string, filter *SubscriptionFilter) ([]*RatePlanSubscription, error) {
|
||||||
query := r.db.WithContext(ctx).Where("profile_id = ?", profileID)
|
query := r.db.WithContext(ctx).Where("profile_id = ?", profileID)
|
||||||
+9
-7
@@ -1,4 +1,4 @@
|
|||||||
package currency
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,11 +6,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListExchangeRates retrieves exchange rates based on filter
|
// ListExchangeRates retrieves exchange rates based on filter
|
||||||
func (r *GormRepository) ListExchangeRates(ctx context.Context, filter *ExchangeRateFilter) ([]*ExchangeRate, error) {
|
func (r *GormRepository) ListExchangeRates(ctx context.Context, filter *currency.ExchangeRateFilter) ([]*currency.ExchangeRate, error) {
|
||||||
query := r.db.WithContext(ctx).Model(&ExchangeRateModel{})
|
query := r.db.WithContext(ctx).Model(¤cy.ExchangeRateModel{})
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if filter.FromCurrency != "" {
|
if filter.FromCurrency != "" {
|
||||||
@@ -50,13 +52,13 @@ func (r *GormRepository) ListExchangeRates(ctx context.Context, filter *Exchange
|
|||||||
query = query.Offset(filter.Offset)
|
query = query.Offset(filter.Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
var models []ExchangeRateModel
|
var models []currency.ExchangeRateModel
|
||||||
if err := query.Find(&models).Error; err != nil {
|
if err := query.Find(&models).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to list exchange rates")
|
r.logger.WithError(err).Error("Failed to list exchange rates")
|
||||||
return nil, fmt.Errorf("failed to list exchange rates: %w", err)
|
return nil, fmt.Errorf("failed to list exchange rates: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rates := make([]*ExchangeRate, 0, len(models))
|
rates := make([]*currency.ExchangeRate, 0, len(models))
|
||||||
for _, model := range models {
|
for _, model := range models {
|
||||||
rate, err := r.modelToExchangeRate(&model)
|
rate, err := r.modelToExchangeRate(&model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -70,9 +72,9 @@ func (r *GormRepository) ListExchangeRates(ctx context.Context, filter *Exchange
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetLatestExchangeRate gets the latest valid exchange rate
|
// GetLatestExchangeRate gets the latest valid exchange rate
|
||||||
func (r *GormRepository) GetLatestExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*ExchangeRate, error) {
|
func (r *GormRepository) GetLatestExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*currency.ExchangeRate, error) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
var model ExchangeRateModel
|
var model currency.ExchangeRateModel
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).
|
if err := r.db.WithContext(ctx).
|
||||||
Where("from_currency = ? AND to_currency = ? AND is_active = ?", fromCurrency, toCurrency, true).
|
Where("from_currency = ? AND to_currency = ? AND is_active = ?", fromCurrency, toCurrency, true).
|
||||||
+14
-12
@@ -1,14 +1,16 @@
|
|||||||
package currency
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateTransaction creates a new transaction
|
// CreateTransaction creates a new transaction
|
||||||
func (r *GormRepository) CreateTransaction(ctx context.Context, transaction *Transaction) error {
|
func (r *GormRepository) CreateTransaction(ctx context.Context, transaction *currency.Transaction) error {
|
||||||
model := r.transactionToModel(transaction)
|
model := r.transactionToModel(transaction)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
|
||||||
@@ -20,8 +22,8 @@ func (r *GormRepository) CreateTransaction(ctx context.Context, transaction *Tra
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTransaction retrieves a transaction by ID
|
// GetTransaction retrieves a transaction by ID
|
||||||
func (r *GormRepository) GetTransaction(ctx context.Context, id string) (*Transaction, error) {
|
func (r *GormRepository) GetTransaction(ctx context.Context, id string) (*currency.Transaction, error) {
|
||||||
var model TransactionModel
|
var model currency.TransactionModel
|
||||||
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&model).Error; err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
return nil, fmt.Errorf("transaction not found: %s", id)
|
return nil, fmt.Errorf("transaction not found: %s", id)
|
||||||
@@ -34,7 +36,7 @@ func (r *GormRepository) GetTransaction(ctx context.Context, id string) (*Transa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTransaction updates an existing transaction
|
// UpdateTransaction updates an existing transaction
|
||||||
func (r *GormRepository) UpdateTransaction(ctx context.Context, transaction *Transaction) error {
|
func (r *GormRepository) UpdateTransaction(ctx context.Context, transaction *currency.Transaction) error {
|
||||||
model := r.transactionToModel(transaction)
|
model := r.transactionToModel(transaction)
|
||||||
|
|
||||||
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
if err := r.db.WithContext(ctx).Save(model).Error; err != nil {
|
||||||
@@ -47,7 +49,7 @@ func (r *GormRepository) UpdateTransaction(ctx context.Context, transaction *Tra
|
|||||||
|
|
||||||
// DeleteTransaction deletes a transaction
|
// DeleteTransaction deletes a transaction
|
||||||
func (r *GormRepository) DeleteTransaction(ctx context.Context, id string) error {
|
func (r *GormRepository) DeleteTransaction(ctx context.Context, id string) error {
|
||||||
if err := r.db.WithContext(ctx).Delete(&TransactionModel{}, "id = ?", id).Error; err != nil {
|
if err := r.db.WithContext(ctx).Delete(¤cy.TransactionModel{}, "id = ?", id).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to delete transaction")
|
r.logger.WithError(err).Error("Failed to delete transaction")
|
||||||
return fmt.Errorf("failed to delete transaction: %w", err)
|
return fmt.Errorf("failed to delete transaction: %w", err)
|
||||||
}
|
}
|
||||||
@@ -56,8 +58,8 @@ func (r *GormRepository) DeleteTransaction(ctx context.Context, id string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListTransactions retrieves transactions based on filter
|
// ListTransactions retrieves transactions based on filter
|
||||||
func (r *GormRepository) ListTransactions(ctx context.Context, filter *TransactionFilter) ([]*Transaction, error) {
|
func (r *GormRepository) ListTransactions(ctx context.Context, filter *currency.TransactionFilter) ([]*currency.Transaction, error) {
|
||||||
query := r.db.WithContext(ctx).Model(&TransactionModel{})
|
query := r.db.WithContext(ctx).Model(¤cy.TransactionModel{})
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if filter.ProfileID != "" {
|
if filter.ProfileID != "" {
|
||||||
@@ -107,13 +109,13 @@ func (r *GormRepository) ListTransactions(ctx context.Context, filter *Transacti
|
|||||||
query = query.Offset(filter.Offset)
|
query = query.Offset(filter.Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
var models []TransactionModel
|
var models []currency.TransactionModel
|
||||||
if err := query.Find(&models).Error; err != nil {
|
if err := query.Find(&models).Error; err != nil {
|
||||||
r.logger.WithError(err).Error("Failed to list transactions")
|
r.logger.WithError(err).Error("Failed to list transactions")
|
||||||
return nil, fmt.Errorf("failed to list transactions: %w", err)
|
return nil, fmt.Errorf("failed to list transactions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
transactions := make([]*Transaction, 0, len(models))
|
transactions := make([]*currency.Transaction, 0, len(models))
|
||||||
for _, model := range models {
|
for _, model := range models {
|
||||||
tx, err := r.modelToTransaction(&model)
|
tx, err := r.modelToTransaction(&model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -127,8 +129,8 @@ func (r *GormRepository) ListTransactions(ctx context.Context, filter *Transacti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountTransactions counts transactions based on filter
|
// CountTransactions counts transactions based on filter
|
||||||
func (r *GormRepository) CountTransactions(ctx context.Context, filter *TransactionFilter) (int, error) {
|
func (r *GormRepository) CountTransactions(ctx context.Context, filter *currency.TransactionFilter) (int, error) {
|
||||||
query := r.db.WithContext(ctx).Model(&TransactionModel{})
|
query := r.db.WithContext(ctx).Model(¤cy.TransactionModel{})
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if filter.ProfileID != "" {
|
if filter.ProfileID != "" {
|
||||||
+31
-44
@@ -1,21 +1,22 @@
|
|||||||
package currency
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AnalyticsServiceImpl handles currency analytics operations
|
// AnalyticsServiceImpl handles currency analytics operations
|
||||||
type AnalyticsServiceImpl struct {
|
type AnalyticsServiceImpl struct {
|
||||||
repository Repository
|
repository currency.Repository
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAnalyticsService creates a new analytics service
|
// NewAnalyticsService creates a new analytics service
|
||||||
func NewAnalyticsService(repository Repository, logger *logrus.Logger) *AnalyticsServiceImpl {
|
func NewAnalyticsService(repository currency.Repository, logger *logrus.Logger) *AnalyticsServiceImpl {
|
||||||
return &AnalyticsServiceImpl{
|
return &AnalyticsServiceImpl{
|
||||||
repository: repository,
|
repository: repository,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
@@ -23,12 +24,12 @@ func NewAnalyticsService(repository Repository, logger *logrus.Logger) *Analytic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRevenueByCurrency calculates revenue breakdown by currency
|
// GetRevenueByCurrency calculates revenue breakdown by currency
|
||||||
func (s *AnalyticsServiceImpl) GetRevenueByCurrency(ctx context.Context, filter *TransactionFilter) (map[string]float64, error) {
|
func (s *AnalyticsServiceImpl) GetRevenueByCurrency(ctx context.Context, filter *currency.TransactionFilter) (map[string]float64, error) {
|
||||||
if filter == nil {
|
if filter == nil {
|
||||||
filter = &TransactionFilter{}
|
filter = ¤cy.TransactionFilter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.Status = TransactionStatusCompleted
|
filter.Status = currency.TransactionStatusCompleted
|
||||||
|
|
||||||
transactions, err := s.repository.ListTransactions(ctx, filter)
|
transactions, err := s.repository.ListTransactions(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,7 +40,7 @@ func (s *AnalyticsServiceImpl) GetRevenueByCurrency(ctx context.Context, filter
|
|||||||
revenueByCurrency := make(map[string]float64)
|
revenueByCurrency := make(map[string]float64)
|
||||||
|
|
||||||
for _, tx := range transactions {
|
for _, tx := range transactions {
|
||||||
if tx.Type == TransactionTypeSubscription || tx.Type == TransactionTypeUsage || tx.Type == TransactionTypeOverage {
|
if tx.Type == currency.TransactionTypeSubscription || tx.Type == currency.TransactionTypeUsage || tx.Type == currency.TransactionTypeOverage {
|
||||||
revenueByCurrency[tx.Currency] += tx.Amount
|
revenueByCurrency[tx.Currency] += tx.Amount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,9 +49,9 @@ func (s *AnalyticsServiceImpl) GetRevenueByCurrency(ctx context.Context, filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionVolumeByCurrency calculates transaction volume by currency
|
// GetTransactionVolumeByCurrency calculates transaction volume by currency
|
||||||
func (s *AnalyticsServiceImpl) GetTransactionVolumeByCurrency(ctx context.Context, filter *TransactionFilter) (map[string]int64, error) {
|
func (s *AnalyticsServiceImpl) GetTransactionVolumeByCurrency(ctx context.Context, filter *currency.TransactionFilter) (map[string]int64, error) {
|
||||||
if filter == nil {
|
if filter == nil {
|
||||||
filter = &TransactionFilter{}
|
filter = ¤cy.TransactionFilter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
transactions, err := s.repository.ListTransactions(ctx, filter)
|
transactions, err := s.repository.ListTransactions(ctx, filter)
|
||||||
@@ -69,8 +70,8 @@ func (s *AnalyticsServiceImpl) GetTransactionVolumeByCurrency(ctx context.Contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetExchangeRateTrends retrieves exchange rate trends for a currency pair
|
// GetExchangeRateTrends retrieves exchange rate trends for a currency pair
|
||||||
func (s *AnalyticsServiceImpl) GetExchangeRateTrends(ctx context.Context, fromCurrency, toCurrency string, days int) ([]*ExchangeRate, error) {
|
func (s *AnalyticsServiceImpl) GetExchangeRateTrends(ctx context.Context, fromCurrency, toCurrency string, days int) ([]*currency.ExchangeRate, error) {
|
||||||
filter := &ExchangeRateFilter{
|
filter := ¤cy.ExchangeRateFilter{
|
||||||
FromCurrency: fromCurrency,
|
FromCurrency: fromCurrency,
|
||||||
ToCurrency: toCurrency,
|
ToCurrency: toCurrency,
|
||||||
IsValid: &[]bool{false}[0], // Include historical rates
|
IsValid: &[]bool{false}[0], // Include historical rates
|
||||||
@@ -89,15 +90,15 @@ func (s *AnalyticsServiceImpl) GetExchangeRateTrends(ctx context.Context, fromCu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrencyUsageStats retrieves currency usage statistics
|
// GetCurrencyUsageStats retrieves currency usage statistics
|
||||||
func (s *AnalyticsServiceImpl) GetCurrencyUsageStats(ctx context.Context) (*CurrencyUsageStats, error) {
|
func (s *AnalyticsServiceImpl) GetCurrencyUsageStats(ctx context.Context) (*currency.CurrencyUsageStats, error) {
|
||||||
// Get total currencies
|
// Get total currencies
|
||||||
totalCurrencies, err := s.repository.CountCurrencies(ctx, &CurrencyFilter{})
|
totalCurrencies, err := s.repository.CountCurrencies(ctx, ¤cy.CurrencyFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count currencies: %w", err)
|
return nil, fmt.Errorf("failed to count currencies: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get active currencies
|
// Get active currencies
|
||||||
activeCurrencies, err := s.repository.CountCurrencies(ctx, &CurrencyFilter{
|
activeCurrencies, err := s.repository.CountCurrencies(ctx, ¤cy.CurrencyFilter{
|
||||||
IsActive: &[]bool{true}[0],
|
IsActive: &[]bool{true}[0],
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,14 +106,14 @@ func (s *AnalyticsServiceImpl) GetCurrencyUsageStats(ctx context.Context) (*Curr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get total transactions
|
// Get total transactions
|
||||||
totalTransactions, err := s.repository.CountTransactions(ctx, &TransactionFilter{})
|
totalTransactions, err := s.repository.CountTransactions(ctx, ¤cy.TransactionFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count transactions: %w", err)
|
return nil, fmt.Errorf("failed to count transactions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get total volume
|
// Get total volume
|
||||||
transactions, err := s.repository.ListTransactions(ctx, &TransactionFilter{
|
transactions, err := s.repository.ListTransactions(ctx, ¤cy.TransactionFilter{
|
||||||
Status: TransactionStatusCompleted,
|
Status: currency.TransactionStatusCompleted,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get transactions for volume: %w", err)
|
return nil, fmt.Errorf("failed to get transactions for volume: %w", err)
|
||||||
@@ -138,12 +139,12 @@ func (s *AnalyticsServiceImpl) GetCurrencyUsageStats(ctx context.Context) (*Curr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get exchange rate count (using ListExchangeRates for now since CountExchangeRates doesn't exist)
|
// Get exchange rate count (using ListExchangeRates for now since CountExchangeRates doesn't exist)
|
||||||
exchangeRates, err := s.repository.ListExchangeRates(ctx, &ExchangeRateFilter{})
|
exchangeRates, err := s.repository.ListExchangeRates(ctx, ¤cy.ExchangeRateFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count exchange rates: %w", err)
|
return nil, fmt.Errorf("failed to count exchange rates: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CurrencyUsageStats{
|
return ¤cy.CurrencyUsageStats{
|
||||||
TotalCurrencies: totalCurrencies,
|
TotalCurrencies: totalCurrencies,
|
||||||
ActiveCurrencies: activeCurrencies,
|
ActiveCurrencies: activeCurrencies,
|
||||||
TotalTransactions: int64(totalTransactions),
|
TotalTransactions: int64(totalTransactions),
|
||||||
@@ -160,8 +161,8 @@ func (s *AnalyticsServiceImpl) GetMonthlyRevenueTrends(ctx context.Context, mont
|
|||||||
endDate := time.Now()
|
endDate := time.Now()
|
||||||
startDate := endDate.AddDate(0, -months, 0)
|
startDate := endDate.AddDate(0, -months, 0)
|
||||||
|
|
||||||
filter := &TransactionFilter{
|
filter := ¤cy.TransactionFilter{
|
||||||
Status: TransactionStatusCompleted,
|
Status: currency.TransactionStatusCompleted,
|
||||||
FromDate: &startDate,
|
FromDate: &startDate,
|
||||||
ToDate: &endDate,
|
ToDate: &endDate,
|
||||||
}
|
}
|
||||||
@@ -183,18 +184,18 @@ func (s *AnalyticsServiceImpl) GetMonthlyRevenueTrends(ctx context.Context, mont
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTopCurrenciesByRevenue returns top currencies by revenue
|
// GetTopCurrenciesByRevenue returns top currencies by revenue
|
||||||
func (s *AnalyticsServiceImpl) GetTopCurrenciesByRevenue(ctx context.Context, limit int) ([]*CurrencyRevenue, error) {
|
func (s *AnalyticsServiceImpl) GetTopCurrenciesByRevenue(ctx context.Context, limit int) ([]*currency.CurrencyRevenue, error) {
|
||||||
revenueByCurrency, err := s.GetRevenueByCurrency(ctx, &TransactionFilter{
|
revenueByCurrency, err := s.GetRevenueByCurrency(ctx, ¤cy.TransactionFilter{
|
||||||
Status: TransactionStatusCompleted,
|
Status: currency.TransactionStatusCompleted,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to slice and sort
|
// Convert to slice and sort
|
||||||
var currencyRevenues []*CurrencyRevenue
|
var currencyRevenues []*currency.CurrencyRevenue
|
||||||
for currency, revenue := range revenueByCurrency {
|
for currency, revenue := range revenueByCurrency {
|
||||||
currencyRevenues = append(currencyRevenues, &CurrencyRevenue{
|
currencyRevenues = append(currencyRevenues, ¤cy.CurrencyRevenue{
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
Revenue: revenue,
|
Revenue: revenue,
|
||||||
})
|
})
|
||||||
@@ -208,16 +209,10 @@ func (s *AnalyticsServiceImpl) GetTopCurrenciesByRevenue(ctx context.Context, li
|
|||||||
return currencyRevenues, nil
|
return currencyRevenues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrencyRevenue represents revenue for a specific currency
|
|
||||||
type CurrencyRevenue struct {
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
Revenue float64 `json:"revenue"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTransactionTypeAnalytics returns analytics by transaction type
|
// GetTransactionTypeAnalytics returns analytics by transaction type
|
||||||
func (s *AnalyticsServiceImpl) GetTransactionTypeAnalytics(ctx context.Context, filter *TransactionFilter) (map[string]*TransactionTypeStats, error) {
|
func (s *AnalyticsServiceImpl) GetTransactionTypeAnalytics(ctx context.Context, filter *currency.TransactionFilter) (map[string]*currency.TransactionTypeStats, error) {
|
||||||
if filter == nil {
|
if filter == nil {
|
||||||
filter = &TransactionFilter{}
|
filter = ¤cy.TransactionFilter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
transactions, err := s.repository.ListTransactions(ctx, filter)
|
transactions, err := s.repository.ListTransactions(ctx, filter)
|
||||||
@@ -226,13 +221,13 @@ func (s *AnalyticsServiceImpl) GetTransactionTypeAnalytics(ctx context.Context,
|
|||||||
return nil, fmt.Errorf("failed to get transactions: %w", err)
|
return nil, fmt.Errorf("failed to get transactions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
typeStats := make(map[string]*TransactionTypeStats)
|
typeStats := make(map[string]*currency.TransactionTypeStats)
|
||||||
|
|
||||||
for _, tx := range transactions {
|
for _, tx := range transactions {
|
||||||
typeKey := string(tx.Type)
|
typeKey := string(tx.Type)
|
||||||
|
|
||||||
if _, exists := typeStats[typeKey]; !exists {
|
if _, exists := typeStats[typeKey]; !exists {
|
||||||
typeStats[typeKey] = &TransactionTypeStats{
|
typeStats[typeKey] = ¤cy.TransactionTypeStats{
|
||||||
Type: tx.Type,
|
Type: tx.Type,
|
||||||
Count: 0,
|
Count: 0,
|
||||||
Amount: 0.0,
|
Amount: 0.0,
|
||||||
@@ -247,11 +242,3 @@ func (s *AnalyticsServiceImpl) GetTransactionTypeAnalytics(ctx context.Context,
|
|||||||
|
|
||||||
return typeStats, nil
|
return typeStats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionTypeStats represents statistics for a transaction type
|
|
||||||
type TransactionTypeStats struct {
|
|
||||||
Type TransactionType `json:"type"`
|
|
||||||
Count int `json:"count"`
|
|
||||||
Amount float64 `json:"amount"`
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package currency
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+18
-17
@@ -1,36 +1,37 @@
|
|||||||
package currency
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExchangeRateService struct {
|
type ExchangeRateService struct {
|
||||||
repository Repository
|
repository currency.Repository
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
providers []ExchangeRateProvider
|
providers []currency.ExchangeRateProvider
|
||||||
baseCurrency string
|
baseCurrency string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExchangeRateService(repository Repository, logger *logrus.Logger, baseCurrency string) *ExchangeRateService {
|
func NewExchangeRateService(repository currency.Repository, logger *logrus.Logger, baseCurrency string) *ExchangeRateService {
|
||||||
return &ExchangeRateService{
|
return &ExchangeRateService{
|
||||||
repository: repository,
|
repository: repository,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
providers: make([]ExchangeRateProvider, 0),
|
providers: make([]currency.ExchangeRateProvider, 0),
|
||||||
baseCurrency: baseCurrency,
|
baseCurrency: baseCurrency,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) AddProvider(provider ExchangeRateProvider) {
|
func (s *ExchangeRateService) AddProvider(provider currency.ExchangeRateProvider) {
|
||||||
s.providers = append(s.providers, provider)
|
s.providers = append(s.providers, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) GetExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*ExchangeRate, error) {
|
func (s *ExchangeRateService) GetExchangeRate(ctx context.Context, fromCurrency, toCurrency string) (*currency.ExchangeRate, error) {
|
||||||
if fromCurrency == toCurrency {
|
if fromCurrency == toCurrency {
|
||||||
return &ExchangeRate{
|
return ¤cy.ExchangeRate{
|
||||||
FromCurrency: fromCurrency,
|
FromCurrency: fromCurrency,
|
||||||
ToCurrency: toCurrency,
|
ToCurrency: toCurrency,
|
||||||
Rate: 1.0,
|
Rate: 1.0,
|
||||||
@@ -48,7 +49,7 @@ func (s *ExchangeRateService) GetExchangeRate(ctx context.Context, fromCurrency,
|
|||||||
for _, provider := range s.providers {
|
for _, provider := range s.providers {
|
||||||
providerRate, err := provider.GetRate(ctx, fromCurrency, toCurrency)
|
providerRate, err := provider.GetRate(ctx, fromCurrency, toCurrency)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newRate := &ExchangeRate{
|
newRate := ¤cy.ExchangeRate{
|
||||||
ID: fmt.Sprintf("%s_%s_%d", fromCurrency, toCurrency, time.Now().Unix()),
|
ID: fmt.Sprintf("%s_%s_%d", fromCurrency, toCurrency, time.Now().Unix()),
|
||||||
FromCurrency: fromCurrency,
|
FromCurrency: fromCurrency,
|
||||||
ToCurrency: toCurrency,
|
ToCurrency: toCurrency,
|
||||||
@@ -69,7 +70,7 @@ func (s *ExchangeRateService) GetExchangeRate(ctx context.Context, fromCurrency,
|
|||||||
return nil, fmt.Errorf("exchange rate not found: %s to %s", fromCurrency, toCurrency)
|
return nil, fmt.Errorf("exchange rate not found: %s to %s", fromCurrency, toCurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) ConvertAmount(ctx context.Context, amount float64, fromCurrency, toCurrency string) (*CurrencyConversionResponse, error) {
|
func (s *ExchangeRateService) ConvertAmount(ctx context.Context, amount float64, fromCurrency, toCurrency string) (*currency.CurrencyConversionResponse, error) {
|
||||||
rate, err := s.GetExchangeRate(ctx, fromCurrency, toCurrency)
|
rate, err := s.GetExchangeRate(ctx, fromCurrency, toCurrency)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get exchange rate: %w", err)
|
return nil, fmt.Errorf("failed to get exchange rate: %w", err)
|
||||||
@@ -77,7 +78,7 @@ func (s *ExchangeRateService) ConvertAmount(ctx context.Context, amount float64,
|
|||||||
|
|
||||||
convertedAmount := amount * rate.Rate
|
convertedAmount := amount * rate.Rate
|
||||||
|
|
||||||
return &CurrencyConversionResponse{
|
return ¤cy.CurrencyConversionResponse{
|
||||||
OriginalAmount: amount,
|
OriginalAmount: amount,
|
||||||
OriginalCurrency: fromCurrency,
|
OriginalCurrency: fromCurrency,
|
||||||
ConvertedAmount: convertedAmount,
|
ConvertedAmount: convertedAmount,
|
||||||
@@ -101,8 +102,8 @@ func (s *ExchangeRateService) RefreshRates(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) GetRateHistory(ctx context.Context, fromCurrency, toCurrency string, days int) ([]*ExchangeRate, error) {
|
func (s *ExchangeRateService) GetRateHistory(ctx context.Context, fromCurrency, toCurrency string, days int) ([]*currency.ExchangeRate, error) {
|
||||||
filter := &ExchangeRateFilter{
|
filter := ¤cy.ExchangeRateFilter{
|
||||||
FromCurrency: fromCurrency,
|
FromCurrency: fromCurrency,
|
||||||
ToCurrency: toCurrency,
|
ToCurrency: toCurrency,
|
||||||
IsValid: &[]bool{false}[0], // Include historical rates
|
IsValid: &[]bool{false}[0], // Include historical rates
|
||||||
@@ -119,7 +120,7 @@ func (s *ExchangeRateService) GetRateHistory(ctx context.Context, fromCurrency,
|
|||||||
return rates, nil
|
return rates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) UpdateExchangeRate(ctx context.Context, rate *ExchangeRate) error {
|
func (s *ExchangeRateService) UpdateExchangeRate(ctx context.Context, rate *currency.ExchangeRate) error {
|
||||||
if rate.Rate <= 0 {
|
if rate.Rate <= 0 {
|
||||||
return fmt.Errorf("invalid exchange rate: must be positive")
|
return fmt.Errorf("invalid exchange rate: must be positive")
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ func (s *ExchangeRateService) UpdateExchangeRate(ctx context.Context, rate *Exch
|
|||||||
rate.ValidFrom = now
|
rate.ValidFrom = now
|
||||||
rate.IsActive = true
|
rate.IsActive = true
|
||||||
|
|
||||||
filter := &ExchangeRateFilter{
|
filter := ¤cy.ExchangeRateFilter{
|
||||||
FromCurrency: rate.FromCurrency,
|
FromCurrency: rate.FromCurrency,
|
||||||
ToCurrency: rate.ToCurrency,
|
ToCurrency: rate.ToCurrency,
|
||||||
IsValid: &[]bool{true}[0],
|
IsValid: &[]bool{true}[0],
|
||||||
@@ -163,8 +164,8 @@ func (s *ExchangeRateService) UpdateExchangeRate(ctx context.Context, rate *Exch
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ExchangeRateService) GetSupportedCurrencies(ctx context.Context) ([]*Currency, error) {
|
func (s *ExchangeRateService) GetSupportedCurrencies(ctx context.Context) ([]*currency.Currency, error) {
|
||||||
filter := &CurrencyFilter{
|
filter := ¤cy.CurrencyFilter{
|
||||||
IsActive: &[]bool{true}[0],
|
IsActive: &[]bool{true}[0],
|
||||||
}
|
}
|
||||||
|
|
||||||
+28
-27
@@ -1,4 +1,4 @@
|
|||||||
package currency
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,21 +7,22 @@ import (
|
|||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/currency"
|
||||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/rateplan"
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/rateplan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RatePlanCurrencyIntegrator integrates currency system with rate plans
|
// RatePlanCurrencyIntegrator integrates currency system with rate plans
|
||||||
type RatePlanCurrencyIntegrator struct {
|
type RatePlanCurrencyIntegrator struct {
|
||||||
billingService BillingService
|
billingService currency.BillingService
|
||||||
exchangeService *ExchangeRateService
|
exchangeService *ExchangeRateService
|
||||||
ratePlanService rateplan.Service
|
ratePlanService rateplan.Service
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
baseCurrency string
|
baseCurrency string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRatePlanCurrencyIntegrator creates a new rate plan currency integrator
|
// NewRatePlanCurrencyIntegrator creates a new rate plan currency integrator
|
||||||
func NewRatePlanCurrencyIntegrator(
|
func NewRatePlanCurrencyIntegrator(
|
||||||
billingService BillingService,
|
billingService currency.BillingService,
|
||||||
exchangeService *ExchangeRateService,
|
exchangeService *ExchangeRateService,
|
||||||
ratePlanService rateplan.Service,
|
ratePlanService rateplan.Service,
|
||||||
logger *logrus.Logger,
|
logger *logrus.Logger,
|
||||||
@@ -30,9 +31,9 @@ func NewRatePlanCurrencyIntegrator(
|
|||||||
return &RatePlanCurrencyIntegrator{
|
return &RatePlanCurrencyIntegrator{
|
||||||
billingService: billingService,
|
billingService: billingService,
|
||||||
exchangeService: exchangeService,
|
exchangeService: exchangeService,
|
||||||
ratePlanService: rateplanService,
|
ratePlanService: ratePlanService,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
baseCurrency: baseCurrency,
|
baseCurrency: baseCurrency,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ func (rpci *RatePlanCurrencyIntegrator) SubscribeToPlanWithCurrency(ctx context.
|
|||||||
// Convert price to requested currency if needed
|
// Convert price to requested currency if needed
|
||||||
subscriptionPrice := plan.BasePrice
|
subscriptionPrice := plan.BasePrice
|
||||||
exchangeRate := 1.0
|
exchangeRate := 1.0
|
||||||
|
|
||||||
if currency != plan.Currency {
|
if currency != plan.Currency {
|
||||||
conversion, err := rpci.exchangeService.ConvertAmount(ctx, plan.BasePrice, plan.Currency, currency)
|
conversion, err := rpci.exchangeService.ConvertAmount(ctx, plan.BasePrice, plan.Currency, currency)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -60,10 +61,10 @@ func (rpci *RatePlanCurrencyIntegrator) SubscribeToPlanWithCurrency(ctx context.
|
|||||||
|
|
||||||
// Create subscription with currency information
|
// Create subscription with currency information
|
||||||
subscription := &rateplan.RatePlanSubscription{
|
subscription := &rateplan.RatePlanSubscription{
|
||||||
ProfileID: profileID,
|
ProfileID: profileID,
|
||||||
RatePlanID: planID,
|
RatePlanID: planID,
|
||||||
Status: rateplan.SubscriptionStatusActive,
|
Status: rateplan.SubscriptionStatusActive,
|
||||||
StartedAt: time.Now(),
|
StartedAt: time.Now(),
|
||||||
Metadata: map[string]interface{}{
|
Metadata: map[string]interface{}{
|
||||||
"original_currency": plan.Currency,
|
"original_currency": plan.Currency,
|
||||||
"subscription_currency": currency,
|
"subscription_currency": currency,
|
||||||
@@ -89,13 +90,13 @@ func (rpci *RatePlanCurrencyIntegrator) SubscribeToPlanWithCurrency(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process initial billing
|
// Process initial billing
|
||||||
billingReq := &BillingRequest{
|
billingReq := ¤cy.BillingRequest{
|
||||||
ProfileID: profileID,
|
ProfileID: profileID,
|
||||||
SubscriptionID: createdSubscription.ID,
|
SubscriptionID: createdSubscription.ID,
|
||||||
Amount: subscriptionPrice,
|
Amount: subscriptionPrice,
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
Description: fmt.Sprintf("Initial subscription to %s", plan.Name),
|
Description: fmt.Sprintf("Initial subscription to %s", plan.Name),
|
||||||
BillingDate: time.Now(),
|
BillingDate: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = rpci.billingService.ProcessBilling(ctx, billingReq)
|
_, err = rpci.billingService.ProcessBilling(ctx, billingReq)
|
||||||
@@ -115,7 +116,7 @@ func (rpci *RatePlanCurrencyIntegrator) SubscribeToPlanWithCurrency(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculatePlanCostInCurrency calculates the cost of a rate plan in a specific currency
|
// CalculatePlanCostInCurrency calculates the cost of a rate plan in a specific currency
|
||||||
func (rpci *RatePlanCurrencyIntegrator) CalculatePlanCostInCurrency(ctx context.Context, planID string, currency string, usageData *rateplan.RatePlanUsage) (*BillingSummary, error) {
|
func (rpci *RatePlanCurrencyIntegrator) CalculatePlanCostInCurrency(ctx context.Context, planID string, currency string, usageData *rateplan.RatePlanUsage) (*currency.BillingSummary, error) {
|
||||||
// Get the rate plan
|
// Get the rate plan
|
||||||
plan, err := rpci.ratePlanService.GetRatePlan(ctx, planID)
|
plan, err := rpci.ratePlanService.GetRatePlan(ctx, planID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -138,7 +139,7 @@ func (rpci *RatePlanCurrencyIntegrator) CalculatePlanCostInCurrency(ctx context.
|
|||||||
// Convert to requested currency
|
// Convert to requested currency
|
||||||
convertedCost := baseCost
|
convertedCost := baseCost
|
||||||
exchangeRate := 1.0
|
exchangeRate := 1.0
|
||||||
|
|
||||||
if currency != plan.Currency {
|
if currency != plan.Currency {
|
||||||
conversion, err := rpci.exchangeService.ConvertAmount(ctx, baseCost, plan.Currency, currency)
|
conversion, err := rpci.exchangeService.ConvertAmount(ctx, baseCost, plan.Currency, currency)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -149,15 +150,15 @@ func (rpci *RatePlanCurrencyIntegrator) CalculatePlanCostInCurrency(ctx context.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create billing summary
|
// Create billing summary
|
||||||
summary := &BillingSummary{
|
summary := ¤cy.BillingSummary{
|
||||||
ProfileID: usageData.ProfileID,
|
ProfileID: usageData.ProfileID,
|
||||||
TotalAmount: convertedCost,
|
TotalAmount: convertedCost,
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
BaseTotalAmount: baseCost,
|
BaseTotalAmount: baseCost,
|
||||||
BaseCurrency: plan.Currency,
|
BaseCurrency: plan.Currency,
|
||||||
TransactionCount: 1,
|
TransactionCount: 1,
|
||||||
FromDate: time.Now().AddDate(0, -1, 0),
|
FromDate: time.Now().AddDate(0, -1, 0),
|
||||||
ToDate: time.Now(),
|
ToDate: time.Now(),
|
||||||
Breakdown: map[string]interface{}{
|
Breakdown: map[string]interface{}{
|
||||||
"plan_id": planID,
|
"plan_id": planID,
|
||||||
"plan_name": plan.Name,
|
"plan_name": plan.Name,
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
package currency
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -85,7 +85,7 @@ func (rpci *RatePlanCurrencyIntegrator) UpdatePlanCurrency(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update rate plan: %w", err)
|
return fmt.Errorf("failed to update rate plan: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the updated plan for logging
|
// Use the updated plan for logging
|
||||||
plan = updatedPlan
|
plan = updatedPlan
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ func (rpci *RatePlanCurrencyIntegrator) GetCurrencyUsageForPlan(ctx context.Cont
|
|||||||
|
|
||||||
// Count currencies
|
// Count currencies
|
||||||
currencyUsage := make(map[string]int64)
|
currencyUsage := make(map[string]int64)
|
||||||
|
|
||||||
for _, subscription := range subscriptions {
|
for _, subscription := range subscriptions {
|
||||||
currency := rpci.baseCurrency // Default to base currency
|
currency := rpci.baseCurrency // Default to base currency
|
||||||
if subscription.Metadata != nil {
|
if subscription.Metadata != nil {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package service
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package service
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package rateplan
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package service
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
Reference in New Issue
Block a user