-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(analytics): added filter api for dispute analytics (#3724)
- Loading branch information
1 parent
49c71d0
commit 6aeb440
Showing
12 changed files
with
255 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
mod core; | ||
|
||
pub mod filters; | ||
|
||
pub use self::core::get_filters; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use api_models::analytics::{ | ||
disputes::DisputeDimensions, DisputeFilterValue, DisputeFiltersResponse, | ||
GetDisputeFilterRequest, | ||
}; | ||
use error_stack::ResultExt; | ||
|
||
use super::filters::{get_dispute_filter_for_dimension, DisputeFilterRow}; | ||
use crate::{ | ||
errors::{AnalyticsError, AnalyticsResult}, | ||
AnalyticsProvider, | ||
}; | ||
|
||
pub async fn get_filters( | ||
pool: &AnalyticsProvider, | ||
req: GetDisputeFilterRequest, | ||
merchant_id: &String, | ||
) -> AnalyticsResult<DisputeFiltersResponse> { | ||
let mut res = DisputeFiltersResponse::default(); | ||
for dim in req.group_by_names { | ||
let values = match pool { | ||
AnalyticsProvider::Sqlx(pool) => { | ||
get_dispute_filter_for_dimension(dim, merchant_id, &req.time_range, pool) | ||
.await | ||
} | ||
AnalyticsProvider::Clickhouse(pool) => { | ||
get_dispute_filter_for_dimension(dim, merchant_id, &req.time_range, pool) | ||
.await | ||
} | ||
AnalyticsProvider::CombinedCkh(sqlx_pool, ckh_pool) => { | ||
let ckh_result = get_dispute_filter_for_dimension( | ||
dim, | ||
merchant_id, | ||
&req.time_range, | ||
ckh_pool, | ||
) | ||
.await; | ||
let sqlx_result = get_dispute_filter_for_dimension( | ||
dim, | ||
merchant_id, | ||
&req.time_range, | ||
sqlx_pool, | ||
) | ||
.await; | ||
match (&sqlx_result, &ckh_result) { | ||
(Ok(ref sqlx_res), Ok(ref ckh_res)) if sqlx_res != ckh_res => { | ||
router_env::logger::error!(clickhouse_result=?ckh_res, postgres_result=?sqlx_res, "Mismatch between clickhouse & postgres disputes analytics filters") | ||
}, | ||
_ => {} | ||
}; | ||
ckh_result | ||
} | ||
AnalyticsProvider::CombinedSqlx(sqlx_pool, ckh_pool) => { | ||
let ckh_result = get_dispute_filter_for_dimension( | ||
dim, | ||
merchant_id, | ||
&req.time_range, | ||
ckh_pool, | ||
) | ||
.await; | ||
let sqlx_result = get_dispute_filter_for_dimension( | ||
dim, | ||
merchant_id, | ||
&req.time_range, | ||
sqlx_pool, | ||
) | ||
.await; | ||
match (&sqlx_result, &ckh_result) { | ||
(Ok(ref sqlx_res), Ok(ref ckh_res)) if sqlx_res != ckh_res => { | ||
router_env::logger::error!(clickhouse_result=?ckh_res, postgres_result=?sqlx_res, "Mismatch between clickhouse & postgres disputes analytics filters") | ||
}, | ||
_ => {} | ||
}; | ||
sqlx_result | ||
} | ||
} | ||
.change_context(AnalyticsError::UnknownError)? | ||
.into_iter() | ||
.filter_map(|fil: DisputeFilterRow| match dim { | ||
DisputeDimensions::DisputeStatus => fil.dispute_status, | ||
DisputeDimensions::DisputeStage => fil.dispute_stage, | ||
DisputeDimensions::ConnectorStatus => fil.connector_status, | ||
DisputeDimensions::Connector => fil.connector, | ||
}) | ||
.collect::<Vec<String>>(); | ||
res.query_data.push(DisputeFilterValue { | ||
dimension: dim, | ||
values, | ||
}) | ||
} | ||
Ok(res) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
use api_models::analytics::{disputes::DisputeDimensions, Granularity, TimeRange}; | ||
use common_utils::errors::ReportSwitchExt; | ||
use error_stack::ResultExt; | ||
use time::PrimitiveDateTime; | ||
|
||
use crate::{ | ||
query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window}, | ||
types::{AnalyticsCollection, AnalyticsDataSource, FiltersError, FiltersResult, LoadRow}, | ||
}; | ||
pub trait DisputeFilterAnalytics: LoadRow<DisputeFilterRow> {} | ||
|
||
pub async fn get_dispute_filter_for_dimension<T>( | ||
dimension: DisputeDimensions, | ||
merchant: &String, | ||
time_range: &TimeRange, | ||
pool: &T, | ||
) -> FiltersResult<Vec<DisputeFilterRow>> | ||
where | ||
T: AnalyticsDataSource + DisputeFilterAnalytics, | ||
PrimitiveDateTime: ToSql<T>, | ||
AnalyticsCollection: ToSql<T>, | ||
Granularity: GroupByClause<T>, | ||
Aggregate<&'static str>: ToSql<T>, | ||
Window<&'static str>: ToSql<T>, | ||
{ | ||
let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Dispute); | ||
|
||
query_builder.add_select_column(dimension).switch()?; | ||
time_range | ||
.set_filter_clause(&mut query_builder) | ||
.attach_printable("Error filtering time range") | ||
.switch()?; | ||
|
||
query_builder | ||
.add_filter_clause("merchant_id", merchant) | ||
.switch()?; | ||
|
||
query_builder.set_distinct(); | ||
|
||
query_builder | ||
.execute_query::<DisputeFilterRow, _>(pool) | ||
.await | ||
.change_context(FiltersError::QueryBuildingError)? | ||
.change_context(FiltersError::QueryExecutionFailure) | ||
} | ||
#[derive(Debug, serde::Serialize, Eq, PartialEq, serde::Deserialize)] | ||
pub struct DisputeFilterRow { | ||
pub connector: Option<String>, | ||
pub dispute_status: Option<String>, | ||
pub connector_status: Option<String>, | ||
pub dispute_stage: Option<String>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
mod clickhouse; | ||
pub mod core; | ||
pub mod disputes; | ||
pub mod errors; | ||
pub mod metrics; | ||
pub mod payments; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters