Skip to content

Commit

Permalink
fix(analytics): fix bugs in payments page metrics in Analytics V2 das…
Browse files Browse the repository at this point in the history
…hboard (#6654)
  • Loading branch information
tsdk02 authored Nov 28, 2024
1 parent 2c86515 commit 93459fd
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 121 deletions.
10 changes: 8 additions & 2 deletions crates/analytics/src/payment_intents/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,14 @@ impl PaymentIntentMetricAccumulator for PaymentsDistributionAccumulator {
}
}

if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
self.total += total;
if status.as_ref() != &storage_enums::IntentStatus::RequiresCustomerAction
&& status.as_ref() != &storage_enums::IntentStatus::RequiresPaymentMethod
&& status.as_ref() != &storage_enums::IntentStatus::RequiresMerchantAction
&& status.as_ref() != &storage_enums::IntentStatus::RequiresConfirmation
{
if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
self.total += total;
}
}
}
}
Expand Down
71 changes: 4 additions & 67 deletions crates/analytics/src/payment_intents/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ use api_models::analytics::{
},
GetPaymentIntentFiltersRequest, GetPaymentIntentMetricRequest, PaymentIntentFilterValue,
PaymentIntentFiltersResponse, PaymentIntentsAnalyticsMetadata, PaymentIntentsMetricsResponse,
SankeyResponse,
};
use bigdecimal::ToPrimitive;
use common_enums::{Currency, IntentStatus};
use common_enums::Currency;
use common_utils::{errors::CustomResult, types::TimeRange};
use currency_conversion::{conversion::convert, types::ExchangeRates};
use error_stack::ResultExt;
Expand All @@ -24,7 +23,7 @@ use router_env::{
use super::{
filters::{get_payment_intent_filter_for_dimension, PaymentIntentFilterRow},
metrics::PaymentIntentMetricRow,
sankey::{get_sankey_data, SessionizerRefundStatus},
sankey::{get_sankey_data, SankeyRow},
PaymentIntentMetricsAccumulator,
};
use crate::{
Expand All @@ -51,7 +50,7 @@ pub async fn get_sankey(
pool: &AnalyticsProvider,
auth: &AuthInfo,
req: TimeRange,
) -> AnalyticsResult<SankeyResponse> {
) -> AnalyticsResult<Vec<SankeyRow>> {
match pool {
AnalyticsProvider::Sqlx(_) => Err(AnalyticsError::NotImplemented(
"Sankey not implemented for sqlx",
Expand All @@ -62,69 +61,7 @@ pub async fn get_sankey(
let sankey_rows = get_sankey_data(ckh_pool, auth, &req)
.await
.change_context(AnalyticsError::UnknownError)?;
let mut sankey_response = SankeyResponse::default();
for i in sankey_rows {
match (
i.status.as_ref(),
i.refunds_status.unwrap_or_default().as_ref(),
i.attempt_count,
) {
(IntentStatus::Succeeded, SessionizerRefundStatus::FullRefunded, 1) => {
sankey_response.refunded += i.count;
sankey_response.normal_success += i.count
}
(IntentStatus::Succeeded, SessionizerRefundStatus::PartialRefunded, 1) => {
sankey_response.partial_refunded += i.count;
sankey_response.normal_success += i.count
}
(IntentStatus::Succeeded, SessionizerRefundStatus::FullRefunded, _) => {
sankey_response.refunded += i.count;
sankey_response.smart_retried_success += i.count
}
(IntentStatus::Succeeded, SessionizerRefundStatus::PartialRefunded, _) => {
sankey_response.partial_refunded += i.count;
sankey_response.smart_retried_success += i.count
}
(
IntentStatus::Succeeded
| IntentStatus::PartiallyCaptured
| IntentStatus::PartiallyCapturedAndCapturable
| IntentStatus::RequiresCapture,
SessionizerRefundStatus::NotRefunded,
1,
) => sankey_response.normal_success += i.count,
(
IntentStatus::Succeeded
| IntentStatus::PartiallyCaptured
| IntentStatus::PartiallyCapturedAndCapturable
| IntentStatus::RequiresCapture,
SessionizerRefundStatus::NotRefunded,
_,
) => sankey_response.smart_retried_success += i.count,
(IntentStatus::Failed, _, 1) => sankey_response.normal_failure += i.count,
(IntentStatus::Failed, _, _) => {
sankey_response.smart_retried_failure += i.count
}
(IntentStatus::Cancelled, _, _) => sankey_response.cancelled += i.count,
(IntentStatus::Processing, _, _) => sankey_response.pending += i.count,
(IntentStatus::RequiresCustomerAction, _, _) => {
sankey_response.customer_awaited += i.count
}
(IntentStatus::RequiresMerchantAction, _, _) => {
sankey_response.merchant_awaited += i.count
}
(IntentStatus::RequiresPaymentMethod, _, _) => {
sankey_response.pm_awaited += i.count
}
(IntentStatus::RequiresConfirmation, _, _) => {
sankey_response.confirmation_awaited += i.count
}
i @ (_, _, _) => {
router_env::logger::error!(status=?i, "Unknown status in sankey data");
}
}
}
Ok(sankey_response)
Ok(sankey_rows)
}
}
}
Expand Down
78 changes: 50 additions & 28 deletions crates/analytics/src/payment_intents/sankey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,26 @@ use common_utils::{
};
use error_stack::ResultExt;
use router_env::logger;
use time::PrimitiveDateTime;

use crate::{
clickhouse::ClickhouseClient,
query::{Aggregate, QueryBuilder, QueryFilter},
types::{AnalyticsCollection, DBEnumWrapper, MetricsError, MetricsResult},
};

#[derive(Debug, PartialEq, Eq, serde::Deserialize, Hash)]
pub struct PaymentIntentMetricRow {
pub profile_id: Option<String>,
pub connector: Option<String>,
pub authentication_type: Option<DBEnumWrapper<enums::AuthenticationType>>,
pub payment_method: Option<String>,
pub payment_method_type: Option<String>,
pub card_network: Option<String>,
pub merchant_id: Option<String>,
pub card_last_4: Option<String>,
pub card_issuer: Option<String>,
pub error_reason: Option<String>,
pub first_attempt: Option<i64>,
pub total: Option<bigdecimal::BigDecimal>,
pub count: Option<i64>,
#[serde(with = "common_utils::custom_serde::iso8601::option")]
pub start_bucket: Option<PrimitiveDateTime>,
#[serde(with = "common_utils::custom_serde::iso8601::option")]
pub end_bucket: Option<PrimitiveDateTime>,
}

#[derive(
Debug, Default, serde::Deserialize, strum::AsRefStr, strum::EnumString, strum::Display,
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
PartialEq,
serde::Deserialize,
serde::Serialize,
strum::Display,
strum::EnumIter,
strum::EnumString,
)]
#[serde(rename_all = "snake_case")]
pub enum SessionizerRefundStatus {
Expand All @@ -45,13 +34,36 @@ pub enum SessionizerRefundStatus {
PartialRefunded,
}

#[derive(Debug, serde::Deserialize)]
#[derive(
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
PartialEq,
serde::Deserialize,
serde::Serialize,
strum::Display,
strum::EnumIter,
strum::EnumString,
)]
#[serde(rename_all = "snake_case")]
pub enum SessionizerDisputeStatus {
DisputePresent,
#[default]
NotDisputed,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct SankeyRow {
pub count: i64,
pub status: DBEnumWrapper<enums::IntentStatus>,
#[serde(default)]
pub refunds_status: Option<DBEnumWrapper<SessionizerRefundStatus>>,
pub attempt_count: i64,
pub count: i64,
#[serde(default)]
pub dispute_status: Option<DBEnumWrapper<SessionizerDisputeStatus>>,
pub first_attempt: i64,
}

impl TryInto<SankeyRow> for serde_json::Value {
Expand Down Expand Up @@ -90,7 +102,12 @@ pub async fn get_sankey_data(
.change_context(MetricsError::QueryBuildingError)?;

query_builder
.add_select_column("attempt_count")
.add_select_column("dispute_status")
.attach_printable("Error adding select clause")
.change_context(MetricsError::QueryBuildingError)?;

query_builder
.add_select_column("(attempt_count = 1) as first_attempt")
.attach_printable("Error adding select clause")
.change_context(MetricsError::QueryBuildingError)?;

Expand All @@ -112,7 +129,12 @@ pub async fn get_sankey_data(
.change_context(MetricsError::QueryBuildingError)?;

query_builder
.add_group_by_clause("attempt_count")
.add_group_by_clause("dispute_status")
.attach_printable("Error adding group by clause")
.change_context(MetricsError::QueryBuildingError)?;

query_builder
.add_group_by_clause("first_attempt")
.attach_printable("Error adding group by clause")
.change_context(MetricsError::QueryBuildingError)?;

Expand Down
19 changes: 13 additions & 6 deletions crates/analytics/src/payments/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,19 @@ impl PaymentMetricAccumulator for PaymentsDistributionAccumulator {
}
}
}
if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
self.total += total;
if metrics.first_attempt.unwrap_or(false) {
self.total_without_retries += total;
} else {
self.total_with_only_retries += total;
if status.as_ref() != &storage_enums::AttemptStatus::AuthenticationFailed
&& status.as_ref() != &storage_enums::AttemptStatus::PaymentMethodAwaited
&& status.as_ref() != &storage_enums::AttemptStatus::DeviceDataCollectionPending
&& status.as_ref() != &storage_enums::AttemptStatus::ConfirmationAwaited
&& status.as_ref() != &storage_enums::AttemptStatus::Unresolved
{
if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
self.total += total;
if metrics.first_attempt.unwrap_or(false) {
self.total_without_retries += total;
} else {
self.total_with_only_retries += total;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,6 @@ where
.switch()?;
}

outer_query_builder
.set_limit_by(5, &filtered_dimensions)
.attach_printable("Error adding limit clause")
.switch()?;

outer_query_builder
.execute_query::<PaymentMetricRow, _>(pool)
.await
Expand Down
18 changes: 5 additions & 13 deletions crates/api_models/src/analytics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,17 +458,9 @@ pub struct GetDisputeMetricRequest {
#[derive(Clone, Debug, Default, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub struct SankeyResponse {
pub normal_success: i64,
pub normal_failure: i64,
pub cancelled: i64,
pub smart_retried_success: i64,
pub smart_retried_failure: i64,
pub pending: i64,
pub partial_refunded: i64,
pub refunded: i64,
pub disputed: i64,
pub pm_awaited: i64,
pub customer_awaited: i64,
pub merchant_awaited: i64,
pub confirmation_awaited: i64,
pub count: i64,
pub status: String,
pub refunds_status: Option<String>,
pub dispute_status: Option<String>,
pub first_attempt: i64,
}

0 comments on commit 93459fd

Please sign in to comment.