mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
feat(analytics): implement currency conversion to power multi-currency aggregation (#6418)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -32,7 +32,10 @@ pub mod routes {
|
||||
|
||||
use crate::{
|
||||
consts::opensearch::SEARCH_INDEXES,
|
||||
core::{api_locking, errors::user::UserErrors, verification::utils},
|
||||
core::{
|
||||
api_locking, currency::get_forex_exchange_rates, errors::user::UserErrors,
|
||||
verification::utils,
|
||||
},
|
||||
db::{user::UserInterface, user_role::ListUserRolesByUserIdPayload},
|
||||
routes::AppState,
|
||||
services::{
|
||||
@ -397,7 +400,8 @@ pub mod routes {
|
||||
org_id: org_id.clone(),
|
||||
merchant_ids: vec![merchant_id.clone()],
|
||||
};
|
||||
analytics::payments::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payments::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
@ -435,7 +439,8 @@ pub mod routes {
|
||||
let auth: AuthInfo = AuthInfo::OrgLevel {
|
||||
org_id: org_id.clone(),
|
||||
};
|
||||
analytics::payments::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payments::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
@ -480,7 +485,8 @@ pub mod routes {
|
||||
merchant_id: merchant_id.clone(),
|
||||
profile_ids: vec![profile_id.clone()],
|
||||
};
|
||||
analytics::payments::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payments::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
@ -520,7 +526,8 @@ pub mod routes {
|
||||
org_id: org_id.clone(),
|
||||
merchant_ids: vec![merchant_id.clone()],
|
||||
};
|
||||
analytics::payment_intents::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payment_intents::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
@ -558,7 +565,8 @@ pub mod routes {
|
||||
let auth: AuthInfo = AuthInfo::OrgLevel {
|
||||
org_id: org_id.clone(),
|
||||
};
|
||||
analytics::payment_intents::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payment_intents::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
@ -603,7 +611,8 @@ pub mod routes {
|
||||
merchant_id: merchant_id.clone(),
|
||||
profile_ids: vec![profile_id.clone()],
|
||||
};
|
||||
analytics::payment_intents::get_metrics(&state.pool, &auth, req)
|
||||
let ex_rates = get_forex_exchange_rates(state.clone()).await?;
|
||||
analytics::payment_intents::get_metrics(&state.pool, &ex_rates, &auth, req)
|
||||
.await
|
||||
.map(ApplicationResponse::Json)
|
||||
},
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use analytics::errors::AnalyticsError;
|
||||
use common_utils::errors::CustomResult;
|
||||
use currency_conversion::types::ExchangeRates;
|
||||
use error_stack::ResultExt;
|
||||
|
||||
use crate::{
|
||||
@ -46,3 +48,19 @@ pub async fn convert_forex(
|
||||
.change_context(ApiErrorResponse::InternalServerError)?,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_forex_exchange_rates(
|
||||
state: SessionState,
|
||||
) -> CustomResult<ExchangeRates, AnalyticsError> {
|
||||
let forex_api = state.conf.forex_api.get_inner();
|
||||
let rates = get_forex_rates(
|
||||
&state,
|
||||
forex_api.call_delay,
|
||||
forex_api.local_fetch_retry_delay,
|
||||
forex_api.local_fetch_retry_count,
|
||||
)
|
||||
.await
|
||||
.change_context(AnalyticsError::ForexFetchFailed)?;
|
||||
|
||||
Ok((*rates.data).clone())
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ const FALLBACK_FOREX_API_CURRENCY_PREFIX: &str = "USD";
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct FxExchangeRatesCacheEntry {
|
||||
data: Arc<ExchangeRates>,
|
||||
pub data: Arc<ExchangeRates>,
|
||||
timestamp: i64,
|
||||
}
|
||||
|
||||
@ -421,7 +421,13 @@ pub async fn fallback_fetch_forex_rates(
|
||||
conversions.insert(enum_curr, currency_factors);
|
||||
}
|
||||
None => {
|
||||
logger::error!("Rates for {} not received from API", &enum_curr);
|
||||
if enum_curr == enums::Currency::USD {
|
||||
let currency_factors =
|
||||
CurrencyFactors::new(Decimal::new(1, 0), Decimal::new(1, 0));
|
||||
conversions.insert(enum_curr, currency_factors);
|
||||
} else {
|
||||
logger::error!("Rates for {} not received from API", &enum_curr);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user