Bug: feat(analytics): Add refund sessionized metrics for Analytics V2 dashboard



Create the new refund sessionized metrics for Analytics V2 dashboard.
diff --git a/crates/analytics/src/clickhouse.rs b/crates/analytics/src/clickhouse.rs
index f56e875f720..cd870c12b23 100644
--- a/crates/analytics/src/clickhouse.rs
+++ b/crates/analytics/src/clickhouse.rs
@@ -16,7 +16,9 @@ use super::{
         distribution::PaymentDistributionRow, filters::PaymentFilterRow, metrics::PaymentMetricRow,
     },
     query::{Aggregate, ToSql, Window},
-    refunds::{filters::RefundFilterRow, metrics::RefundMetricRow},
+    refunds::{
+        distribution::RefundDistributionRow, filters::RefundFilterRow, metrics::RefundMetricRow,
+    },
     sdk_events::{filters::SdkEventFilter, metrics::SdkEventMetricRow},
     types::{AnalyticsCollection, AnalyticsDataSource, LoadRow, QueryExecutionError},
 };
@@ -170,6 +172,7 @@ impl super::payment_intents::filters::PaymentIntentFilterAnalytics for Clickhous
 impl super::payment_intents::metrics::PaymentIntentMetricAnalytics for ClickhouseClient {}
 impl super::refunds::metrics::RefundMetricAnalytics for ClickhouseClient {}
 impl super::refunds::filters::RefundFilterAnalytics for ClickhouseClient {}
+impl super::refunds::distribution::RefundDistributionAnalytics for ClickhouseClient {}
 impl super::frm::metrics::FrmMetricAnalytics for ClickhouseClient {}
 impl super::frm::filters::FrmFilterAnalytics for ClickhouseClient {}
 impl super::sdk_events::filters::SdkEventFilterAnalytics for ClickhouseClient {}
@@ -300,6 +303,16 @@ impl TryInto<RefundFilterRow> for serde_json::Value {
     }
 }
 
+impl TryInto<RefundDistributionRow> for serde_json::Value {
+    type Error = Report<ParsingError>;
+
+    fn try_into(self) -> Result<RefundDistributionRow, Self::Error> {
+        serde_json::from_value(self).change_context(ParsingError::StructParseFailure(
+            "Failed to parse RefundDistributionRow in clickhouse results",
+        ))
+    }
+}
+
 impl TryInto<FrmMetricRow> for serde_json::Value {
     type Error = Report<ParsingError>;
 
diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs
index 224cd82ccd3..13fdefe864d 100644
--- a/crates/analytics/src/lib.rs
+++ b/crates/analytics/src/lib.rs
@@ -29,6 +29,7 @@ use hyperswitch_interfaces::secrets_interface::{
     secret_state::{RawSecret, SecretStateContainer, SecuredSecret},
     SecretManagementInterface, SecretsManagementError,
 };
+use refunds::distribution::{RefundDistribution, RefundDistributionRow};
 pub use types::AnalyticsDomain;
 pub mod lambda_utils;
 pub mod utils;
@@ -52,7 +53,7 @@ use api_models::analytics::{
     sdk_events::{
         SdkEventDimensions, SdkEventFilters, SdkEventMetrics, SdkEventMetricsBucketIdentifier,
     },
-    Distribution, Granularity, TimeRange,
+    Granularity, PaymentDistributionBody, RefundDistributionBody, TimeRange,
 };
 use clickhouse::ClickhouseClient;
 pub use clickhouse::ClickhouseConfig;
@@ -215,7 +216,7 @@ impl AnalyticsProvider {
 
     pub async fn get_payment_distribution(
         &self,
-        distribution: &Distribution,
+        distribution: &PaymentDistributionBody,
         dimensions: &[PaymentDimensions],
         auth: &AuthInfo,
         filters: &PaymentFilters,
@@ -528,6 +529,116 @@ impl AnalyticsProvider {
         .await
     }
 
+    pub async fn get_refund_distribution(
+        &self,
+        distribution: &RefundDistributionBody,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+    ) -> types::MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>> {
+        // Metrics to get the fetch time for each payment metric
+        metrics::request::record_operation_time(
+            async {
+                match self {
+                        Self::Sqlx(pool) => {
+                        distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                pool,
+                            )
+                            .await
+                    }
+                                        Self::Clickhouse(pool) => {
+                        distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                pool,
+                            )
+                            .await
+                    }
+                                    Self::CombinedCkh(sqlx_pool, ckh_pool) => {
+                        let (ckh_result, sqlx_result) = tokio::join!(distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                ckh_pool,
+                            ),
+                            distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                sqlx_pool,
+                            ));
+                        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 payments analytics distribution")
+                            },
+                            _ => {}
+
+                        };
+
+                        ckh_result
+                    }
+                                    Self::CombinedSqlx(sqlx_pool, ckh_pool) => {
+                        let (ckh_result, sqlx_result) = tokio::join!(distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                ckh_pool,
+                            ),
+                            distribution.distribution_for
+                            .load_distribution(
+                                distribution,
+                                dimensions,
+                                auth,
+                                filters,
+                                granularity,
+                                time_range,
+                                sqlx_pool,
+                            ));
+                        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 payments analytics distribution")
+                            },
+                            _ => {}
+
+                        };
+
+                        sqlx_result
+                    }
+                }
+            },
+            &metrics::METRIC_FETCH_TIME,
+            &distribution.distribution_for,
+            self,
+        )
+        .await
+    }
+
     pub async fn get_frm_metrics(
         &self,
         metric: &FrmMetrics,
diff --git a/crates/analytics/src/payments/distribution.rs b/crates/analytics/src/payments/distribution.rs
index 213b6244574..055572a0805 100644
--- a/crates/analytics/src/payments/distribution.rs
+++ b/crates/analytics/src/payments/distribution.rs
@@ -2,7 +2,7 @@ use api_models::analytics::{
     payments::{
         PaymentDimensions, PaymentDistributions, PaymentFilters, PaymentMetricsBucketIdentifier,
     },
-    Distribution, Granularity, TimeRange,
+    Granularity, PaymentDistributionBody, TimeRange,
 };
 use diesel_models::enums as storage_enums;
 use time::PrimitiveDateTime;
@@ -53,7 +53,7 @@ where
     #[allow(clippy::too_many_arguments)]
     async fn load_distribution(
         &self,
-        distribution: &Distribution,
+        distribution: &PaymentDistributionBody,
         dimensions: &[PaymentDimensions],
         auth: &AuthInfo,
         filters: &PaymentFilters,
@@ -75,7 +75,7 @@ where
 {
     async fn load_distribution(
         &self,
-        distribution: &Distribution,
+        distribution: &PaymentDistributionBody,
         dimensions: &[PaymentDimensions],
         auth: &AuthInfo,
         filters: &PaymentFilters,
diff --git a/crates/analytics/src/payments/distribution/payment_error_message.rs b/crates/analytics/src/payments/distribution/payment_error_message.rs
index 241754ee041..de5cb3ae5e8 100644
--- a/crates/analytics/src/payments/distribution/payment_error_message.rs
+++ b/crates/analytics/src/payments/distribution/payment_error_message.rs
@@ -1,6 +1,6 @@
 use api_models::analytics::{
     payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
-    Distribution, Granularity, TimeRange,
+    Granularity, PaymentDistributionBody, TimeRange,
 };
 use common_utils::errors::ReportSwitchExt;
 use diesel_models::enums as storage_enums;
@@ -31,7 +31,7 @@ where
 {
     async fn load_distribution(
         &self,
-        distribution: &Distribution,
+        distribution: &PaymentDistributionBody,
         dimensions: &[PaymentDimensions],
         auth: &AuthInfo,
         filters: &PaymentFilters,
diff --git a/crates/analytics/src/query.rs b/crates/analytics/src/query.rs
index caa112ec175..cbb0cf6737c 100644
--- a/crates/analytics/src/query.rs
+++ b/crates/analytics/src/query.rs
@@ -9,7 +9,7 @@ use api_models::{
         frm::{FrmDimensions, FrmTransactionType},
         payment_intents::PaymentIntentDimensions,
         payments::{PaymentDimensions, PaymentDistributions},
-        refunds::{RefundDimensions, RefundType},
+        refunds::{RefundDimensions, RefundDistributions, RefundType},
         sdk_events::{SdkEventDimensions, SdkEventNames},
         Granularity,
     },
@@ -488,6 +488,7 @@ impl_to_sql_for_to_string!(
     PaymentIntentDimensions,
     &PaymentDistributions,
     RefundDimensions,
+    &RefundDistributions,
     FrmDimensions,
     PaymentMethod,
     PaymentMethodType,
diff --git a/crates/analytics/src/refunds.rs b/crates/analytics/src/refunds.rs
index 590dc148ebf..ed6f396ccec 100644
--- a/crates/analytics/src/refunds.rs
+++ b/crates/analytics/src/refunds.rs
@@ -1,6 +1,7 @@
 pub mod accumulator;
 mod core;
 
+pub mod distribution;
 pub mod filters;
 pub mod metrics;
 pub mod types;
diff --git a/crates/analytics/src/refunds/accumulator.rs b/crates/analytics/src/refunds/accumulator.rs
index add38c98162..840d46bbab7 100644
--- a/crates/analytics/src/refunds/accumulator.rs
+++ b/crates/analytics/src/refunds/accumulator.rs
@@ -1,19 +1,56 @@
-use api_models::analytics::refunds::RefundMetricsBucketValue;
+use api_models::analytics::refunds::{
+    ErrorMessagesResult, ReasonsResult, RefundMetricsBucketValue,
+};
+use bigdecimal::ToPrimitive;
 use diesel_models::enums as storage_enums;
 
-use super::metrics::RefundMetricRow;
+use super::{distribution::RefundDistributionRow, metrics::RefundMetricRow};
 #[derive(Debug, Default)]
 pub struct RefundMetricsAccumulator {
     pub refund_success_rate: SuccessRateAccumulator,
     pub refund_count: CountAccumulator,
     pub refund_success: CountAccumulator,
-    pub processed_amount: PaymentProcessedAmountAccumulator,
+    pub processed_amount: RefundProcessedAmountAccumulator,
+    pub refund_reason: RefundReasonAccumulator,
+    pub refund_reason_distribution: RefundReasonDistributionAccumulator,
+    pub refund_error_message: RefundReasonAccumulator,
+    pub refund_error_message_distribution: RefundErrorMessageDistributionAccumulator,
 }
 
 #[derive(Debug, Default)]
-pub struct SuccessRateAccumulator {
-    pub success: i64,
+pub struct RefundReasonDistributionRow {
+    pub count: i64,
+    pub total: i64,
+    pub refund_reason: String,
+}
+
+#[derive(Debug, Default)]
+pub struct RefundReasonDistributionAccumulator {
+    pub refund_reason_vec: Vec<RefundReasonDistributionRow>,
+}
+
+#[derive(Debug, Default)]
+pub struct RefundErrorMessageDistributionRow {
+    pub count: i64,
     pub total: i64,
+    pub refund_error_message: String,
+}
+
+#[derive(Debug, Default)]
+pub struct RefundErrorMessageDistributionAccumulator {
+    pub refund_error_message_vec: Vec<RefundErrorMessageDistributionRow>,
+}
+
+#[derive(Debug, Default)]
+#[repr(transparent)]
+pub struct RefundReasonAccumulator {
+    pub count: u64,
+}
+
+#[derive(Debug, Default)]
+pub struct SuccessRateAccumulator {
+    pub success: u32,
+    pub total: u32,
 }
 #[derive(Debug, Default)]
 #[repr(transparent)]
@@ -21,8 +58,8 @@ pub struct CountAccumulator {
     pub count: Option<i64>,
 }
 #[derive(Debug, Default)]
-#[repr(transparent)]
-pub struct PaymentProcessedAmountAccumulator {
+pub struct RefundProcessedAmountAccumulator {
+    pub count: Option<i64>,
     pub total: Option<i64>,
 }
 
@@ -34,6 +71,93 @@ pub trait RefundMetricAccumulator {
     fn collect(self) -> Self::MetricOutput;
 }
 
+pub trait RefundDistributionAccumulator {
+    type DistributionOutput;
+
+    fn add_distribution_bucket(&mut self, distribution: &RefundDistributionRow);
+
+    fn collect(self) -> Self::DistributionOutput;
+}
+
+impl RefundDistributionAccumulator for RefundReasonDistributionAccumulator {
+    type DistributionOutput = Option<Vec<ReasonsResult>>;
+
+    fn add_distribution_bucket(&mut self, distribution: &RefundDistributionRow) {
+        self.refund_reason_vec.push(RefundReasonDistributionRow {
+            count: distribution.count.unwrap_or_default(),
+            total: distribution
+                .total
+                .clone()
+                .map(|i| i.to_i64().unwrap_or_default())
+                .unwrap_or_default(),
+            refund_reason: distribution.refund_reason.clone().unwrap_or_default(),
+        })
+    }
+
+    fn collect(mut self) -> Self::DistributionOutput {
+        if self.refund_reason_vec.is_empty() {
+            None
+        } else {
+            self.refund_reason_vec.sort_by(|a, b| b.count.cmp(&a.count));
+            let mut res: Vec<ReasonsResult> = Vec::new();
+            for val in self.refund_reason_vec.into_iter() {
+                let perc = f64::from(u32::try_from(val.count).ok()?) * 100.0
+                    / f64::from(u32::try_from(val.total).ok()?);
+
+                res.push(ReasonsResult {
+                    reason: val.refund_reason,
+                    count: val.count,
+                    percentage: (perc * 100.0).round() / 100.0,
+                })
+            }
+
+            Some(res)
+        }
+    }
+}
+
+impl RefundDistributionAccumulator for RefundErrorMessageDistributionAccumulator {
+    type DistributionOutput = Option<Vec<ErrorMessagesResult>>;
+
+    fn add_distribution_bucket(&mut self, distribution: &RefundDistributionRow) {
+        self.refund_error_message_vec
+            .push(RefundErrorMessageDistributionRow {
+                count: distribution.count.unwrap_or_default(),
+                total: distribution
+                    .total
+                    .clone()
+                    .map(|i| i.to_i64().unwrap_or_default())
+                    .unwrap_or_default(),
+                refund_error_message: distribution
+                    .refund_error_message
+                    .clone()
+                    .unwrap_or_default(),
+            })
+    }
+
+    fn collect(mut self) -> Self::DistributionOutput {
+        if self.refund_error_message_vec.is_empty() {
+            None
+        } else {
+            self.refund_error_message_vec
+                .sort_by(|a, b| b.count.cmp(&a.count));
+            let mut res: Vec<ErrorMessagesResult> = Vec::new();
+            for val in self.refund_error_message_vec.into_iter() {
+                let perc = f64::from(u32::try_from(val.count).ok()?) * 100.0
+                    / f64::from(u32::try_from(val.total).ok()?);
+
+                res.push(ErrorMessagesResult {
+                    error_message: val.refund_error_message,
+                    count: val.count,
+                    percentage: (perc * 100.0).round() / 100.0,
+                })
+            }
+
+            Some(res)
+        }
+    }
+}
+
 impl RefundMetricAccumulator for CountAccumulator {
     type MetricOutput = Option<u64>;
     #[inline]
@@ -50,62 +174,103 @@ impl RefundMetricAccumulator for CountAccumulator {
     }
 }
 
-impl RefundMetricAccumulator for PaymentProcessedAmountAccumulator {
-    type MetricOutput = (Option<u64>, Option<u64>);
+impl RefundMetricAccumulator for RefundProcessedAmountAccumulator {
+    type MetricOutput = (Option<u64>, Option<u64>, Option<u64>);
     #[inline]
     fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
         self.total = match (
             self.total,
-            metrics
-                .total
-                .as_ref()
-                .and_then(bigdecimal::ToPrimitive::to_i64),
+            metrics.total.as_ref().and_then(ToPrimitive::to_i64),
         ) {
             (None, None) => None,
             (None, i @ Some(_)) | (i @ Some(_), None) => i,
             (Some(a), Some(b)) => Some(a + b),
-        }
+        };
+
+        self.count = match (self.count, metrics.count) {
+            (None, None) => None,
+            (None, i @ Some(_)) | (i @ Some(_), None) => i,
+            (Some(a), Some(b)) => Some(a + b),
+        };
     }
     #[inline]
     fn collect(self) -> Self::MetricOutput {
-        (self.total.and_then(|i| u64::try_from(i).ok()), Some(0))
+        let total = u64::try_from(self.total.unwrap_or_default()).ok();
+        let count = self.count.and_then(|i| u64::try_from(i).ok());
+
+        (total, count, Some(0))
     }
 }
 
 impl RefundMetricAccumulator for SuccessRateAccumulator {
-    type MetricOutput = Option<f64>;
+    type MetricOutput = (Option<u32>, Option<u32>, Option<f64>);
 
     fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
         if let Some(ref refund_status) = metrics.refund_status {
             if refund_status.as_ref() == &storage_enums::RefundStatus::Success {
-                self.success += metrics.count.unwrap_or_default();
+                if let Some(success) = metrics
+                    .count
+                    .and_then(|success| u32::try_from(success).ok())
+                {
+                    self.success += success;
+                }
             }
         };
-        self.total += metrics.count.unwrap_or_default();
+        if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
+            self.total += total;
+        }
     }
 
     fn collect(self) -> Self::MetricOutput {
-        if self.total <= 0 {
-            None
+        if self.total == 0 {
+            (None, None, None)
         } else {
-            Some(
-                f64::from(u32::try_from(self.success).ok()?) * 100.0
-                    / f64::from(u32::try_from(self.total).ok()?),
-            )
+            let success = Some(self.success);
+            let total = Some(self.total);
+            let success_rate = match (success, total) {
+                (Some(s), Some(t)) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
+                _ => None,
+            };
+            (success, total, success_rate)
+        }
+    }
+}
+
+impl RefundMetricAccumulator for RefundReasonAccumulator {
+    type MetricOutput = Option<u64>;
+
+    fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
+        if let Some(count) = metrics.count {
+            if let Ok(count_u64) = u64::try_from(count) {
+                self.count += count_u64;
+            }
         }
     }
+
+    fn collect(self) -> Self::MetricOutput {
+        Some(self.count)
+    }
 }
 
 impl RefundMetricsAccumulator {
     pub fn collect(self) -> RefundMetricsBucketValue {
-        let (refund_processed_amount, refund_processed_amount_in_usd) =
+        let (successful_refunds, total_refunds, refund_success_rate) =
+            self.refund_success_rate.collect();
+        let (refund_processed_amount, refund_processed_count, refund_processed_amount_in_usd) =
             self.processed_amount.collect();
         RefundMetricsBucketValue {
-            refund_success_rate: self.refund_success_rate.collect(),
+            successful_refunds,
+            total_refunds,
+            refund_success_rate,
             refund_count: self.refund_count.collect(),
             refund_success_count: self.refund_success.collect(),
             refund_processed_amount,
             refund_processed_amount_in_usd,
+            refund_processed_count,
+            refund_reason_distribution: self.refund_reason_distribution.collect(),
+            refund_error_message_distribution: self.refund_error_message_distribution.collect(),
+            refund_reason_count: self.refund_reason.collect(),
+            refund_error_message_count: self.refund_error_message.collect(),
         }
     }
 }
diff --git a/crates/analytics/src/refunds/core.rs b/crates/analytics/src/refunds/core.rs
index e3bfa4da9d1..205600b9259 100644
--- a/crates/analytics/src/refunds/core.rs
+++ b/crates/analytics/src/refunds/core.rs
@@ -1,15 +1,17 @@
 #![allow(dead_code)]
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 
 use api_models::analytics::{
     refunds::{
-        RefundDimensions, RefundMetrics, RefundMetricsBucketIdentifier, RefundMetricsBucketResponse,
+        RefundDimensions, RefundDistributions, RefundMetrics, RefundMetricsBucketIdentifier,
+        RefundMetricsBucketResponse,
     },
     GetRefundFilterRequest, GetRefundMetricRequest, RefundFilterValue, RefundFiltersResponse,
     RefundsAnalyticsMetadata, RefundsMetricsResponse,
 };
 use bigdecimal::ToPrimitive;
 use common_enums::Currency;
+use common_utils::errors::CustomResult;
 use currency_conversion::{conversion::convert, types::ExchangeRates};
 use error_stack::ResultExt;
 use router_env::{
@@ -19,17 +21,31 @@ use router_env::{
 };
 
 use super::{
+    distribution::RefundDistributionRow,
     filters::{get_refund_filter_for_dimension, RefundFilterRow},
+    metrics::RefundMetricRow,
     RefundMetricsAccumulator,
 };
 use crate::{
     enums::AuthInfo,
     errors::{AnalyticsError, AnalyticsResult},
     metrics,
-    refunds::RefundMetricAccumulator,
+    refunds::{accumulator::RefundDistributionAccumulator, RefundMetricAccumulator},
     AnalyticsProvider,
 };
 
+#[derive(Debug)]
+pub enum TaskType {
+    MetricTask(
+        RefundMetrics,
+        CustomResult<HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>, AnalyticsError>,
+    ),
+    DistributionTask(
+        RefundDistributions,
+        CustomResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>, AnalyticsError>,
+    ),
+}
+
 pub async fn get_metrics(
     pool: &AnalyticsProvider,
     ex_rates: &ExchangeRates,
@@ -62,65 +78,145 @@ pub async fn get_metrics(
                     )
                     .await
                     .change_context(AnalyticsError::UnknownError);
-                (metric_type, data)
+                TaskType::MetricTask(metric_type, data)
+            }
+            .instrument(task_span),
+        );
+    }
+
+    if let Some(distribution) = req.clone().distribution {
+        let req = req.clone();
+        let pool = pool.clone();
+        let task_span = tracing::debug_span!(
+            "analytics_refunds_distribution_query",
+            refund_distribution = distribution.distribution_for.as_ref()
+        );
+
+        let auth_scoped = auth.to_owned();
+        set.spawn(
+            async move {
+                let data = pool
+                    .get_refund_distribution(
+                        &distribution,
+                        &req.group_by_names.clone(),
+                        &auth_scoped,
+                        &req.filters,
+                        &req.time_series.map(|t| t.granularity),
+                        &req.time_range,
+                    )
+                    .await
+                    .change_context(AnalyticsError::UnknownError);
+                TaskType::DistributionTask(distribution.distribution_for, data)
             }
             .instrument(task_span),
         );
     }
 
-    while let Some((metric, data)) = set
+    while let Some(task_type) = set
         .join_next()
         .await
         .transpose()
         .change_context(AnalyticsError::UnknownError)?
     {
-        let data = data?;
-        let attributes = &add_attributes([
-            ("metric_type", metric.to_string()),
-            ("source", pool.to_string()),
-        ]);
-
-        let value = u64::try_from(data.len());
-        if let Ok(val) = value {
-            metrics::BUCKETS_FETCHED.record(&metrics::CONTEXT, val, attributes);
-            logger::debug!("Attributes: {:?}, Buckets fetched: {}", attributes, val);
-        }
+        match task_type {
+            TaskType::MetricTask(metric, data) => {
+                let data = data?;
+                let attributes = &add_attributes([
+                    ("metric_type", metric.to_string()),
+                    ("source", pool.to_string()),
+                ]);
 
-        for (id, value) in data {
-            logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for metric {metric}");
-            let metrics_builder = metrics_accumulator.entry(id).or_default();
-            match metric {
-                RefundMetrics::RefundSuccessRate | RefundMetrics::SessionizedRefundSuccessRate => {
-                    metrics_builder
-                        .refund_success_rate
-                        .add_metrics_bucket(&value)
+                let value = u64::try_from(data.len());
+                if let Ok(val) = value {
+                    metrics::BUCKETS_FETCHED.record(&metrics::CONTEXT, val, attributes);
+                    logger::debug!("Attributes: {:?}, Buckets fetched: {}", attributes, val);
                 }
-                RefundMetrics::RefundCount | RefundMetrics::SessionizedRefundCount => {
-                    metrics_builder.refund_count.add_metrics_bucket(&value)
+
+                for (id, value) in data {
+                    logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for metric {metric}");
+                    let metrics_builder = metrics_accumulator.entry(id).or_default();
+                    match metric {
+                        RefundMetrics::RefundSuccessRate
+                        | RefundMetrics::SessionizedRefundSuccessRate => metrics_builder
+                            .refund_success_rate
+                            .add_metrics_bucket(&value),
+                        RefundMetrics::RefundCount | RefundMetrics::SessionizedRefundCount => {
+                            metrics_builder.refund_count.add_metrics_bucket(&value)
+                        }
+                        RefundMetrics::RefundSuccessCount
+                        | RefundMetrics::SessionizedRefundSuccessCount => {
+                            metrics_builder.refund_success.add_metrics_bucket(&value)
+                        }
+                        RefundMetrics::RefundProcessedAmount
+                        | RefundMetrics::SessionizedRefundProcessedAmount => {
+                            metrics_builder.processed_amount.add_metrics_bucket(&value)
+                        }
+                        RefundMetrics::SessionizedRefundReason => {
+                            metrics_builder.refund_reason.add_metrics_bucket(&value)
+                        }
+                        RefundMetrics::SessionizedRefundErrorMessage => metrics_builder
+                            .refund_error_message
+                            .add_metrics_bucket(&value),
+                    }
                 }
-                RefundMetrics::RefundSuccessCount
-                | RefundMetrics::SessionizedRefundSuccessCount => {
-                    metrics_builder.refund_success.add_metrics_bucket(&value)
+
+                logger::debug!(
+                    "Analytics Accumulated Results: metric: {}, results: {:#?}",
+                    metric,
+                    metrics_accumulator
+                );
+            }
+            TaskType::DistributionTask(distribution, data) => {
+                let data = data?;
+                let attributes = &add_attributes([
+                    ("distribution_type", distribution.to_string()),
+                    ("source", pool.to_string()),
+                ]);
+                let value = u64::try_from(data.len());
+                if let Ok(val) = value {
+                    metrics::BUCKETS_FETCHED.record(&metrics::CONTEXT, val, attributes);
+                    logger::debug!("Attributes: {:?}, Buckets fetched: {}", attributes, val);
                 }
-                RefundMetrics::RefundProcessedAmount
-                | RefundMetrics::SessionizedRefundProcessedAmount => {
-                    metrics_builder.processed_amount.add_metrics_bucket(&value)
+
+                for (id, value) in data {
+                    logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for distribution {distribution}");
+
+                    let metrics_builder = metrics_accumulator.entry(id).or_default();
+                    match distribution {
+                        RefundDistributions::SessionizedRefundReason => metrics_builder
+                            .refund_reason_distribution
+                            .add_distribution_bucket(&value),
+                        RefundDistributions::SessionizedRefundErrorMessage => metrics_builder
+                            .refund_error_message_distribution
+                            .add_distribution_bucket(&value),
+                    }
                 }
+                logger::debug!(
+                    "Analytics Accumulated Results: distribution: {}, results: {:#?}",
+                    distribution,
+                    metrics_accumulator
+                );
             }
         }
-
-        logger::debug!(
-            "Analytics Accumulated Results: metric: {}, results: {:#?}",
-            metric,
-            metrics_accumulator
-        );
     }
+
+    let mut success = 0;
+    let mut total = 0;
     let mut total_refund_processed_amount = 0;
     let mut total_refund_processed_amount_in_usd = 0;
+    let mut total_refund_processed_count = 0;
+    let mut total_refund_reason_count = 0;
+    let mut total_refund_error_message_count = 0;
     let query_data: Vec<RefundMetricsBucketResponse> = metrics_accumulator
         .into_iter()
         .map(|(id, val)| {
             let mut collected_values = val.collect();
+            if let Some(success_count) = collected_values.successful_refunds {
+                success += success_count;
+            }
+            if let Some(total_count) = collected_values.total_refunds {
+                total += total_count;
+            }
             if let Some(amount) = collected_values.refund_processed_amount {
                 let amount_in_usd = id
                     .currency
@@ -142,18 +238,34 @@ pub async fn get_metrics(
                 total_refund_processed_amount += amount;
                 total_refund_processed_amount_in_usd += amount_in_usd.unwrap_or(0);
             }
+            if let Some(count) = collected_values.refund_processed_count {
+                total_refund_processed_count += count;
+            }
+            if let Some(total_count) = collected_values.refund_reason_count {
+                total_refund_reason_count += total_count;
+            }
+            if let Some(total_count) = collected_values.refund_error_message_count {
+                total_refund_error_message_count += total_count;
+            }
             RefundMetricsBucketResponse {
                 values: collected_values,
                 dimensions: id,
             }
         })
         .collect();
-
+    let total_refund_success_rate = match (success, total) {
+        (s, t) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
+        _ => None,
+    };
     Ok(RefundsMetricsResponse {
         query_data,
         meta_data: [RefundsAnalyticsMetadata {
+            total_refund_success_rate,
             total_refund_processed_amount: Some(total_refund_processed_amount),
             total_refund_processed_amount_in_usd: Some(total_refund_processed_amount_in_usd),
+            total_refund_processed_count: Some(total_refund_processed_count),
+            total_refund_reason_count: Some(total_refund_reason_count),
+            total_refund_error_message_count: Some(total_refund_error_message_count),
         }],
     })
 }
@@ -229,6 +341,8 @@ pub async fn get_filters(
             RefundDimensions::Connector => fil.connector,
             RefundDimensions::RefundType => fil.refund_type.map(|i| i.as_ref().to_string()),
             RefundDimensions::ProfileId => fil.profile_id,
+            RefundDimensions::RefundReason => fil.refund_reason,
+            RefundDimensions::RefundErrorMessage => fil.refund_error_message,
         })
         .collect::<Vec<String>>();
         res.query_data.push(RefundFilterValue {
diff --git a/crates/analytics/src/refunds/distribution.rs b/crates/analytics/src/refunds/distribution.rs
new file mode 100644
index 00000000000..962f74acd1a
--- /dev/null
+++ b/crates/analytics/src/refunds/distribution.rs
@@ -0,0 +1,105 @@
+use api_models::analytics::{
+    refunds::{
+        RefundDimensions, RefundDistributions, RefundFilters, RefundMetricsBucketIdentifier,
+        RefundType,
+    },
+    Granularity, RefundDistributionBody, TimeRange,
+};
+use diesel_models::enums as storage_enums;
+use time::PrimitiveDateTime;
+
+use crate::{
+    enums::AuthInfo,
+    query::{Aggregate, GroupByClause, ToSql, Window},
+    types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult},
+};
+
+mod sessionized_distribution;
+
+#[derive(Debug, PartialEq, Eq, serde::Deserialize)]
+pub struct RefundDistributionRow {
+    pub currency: Option<DBEnumWrapper<storage_enums::Currency>>,
+    pub refund_status: Option<DBEnumWrapper<storage_enums::RefundStatus>>,
+    pub connector: Option<String>,
+    pub refund_type: Option<DBEnumWrapper<RefundType>>,
+    pub profile_id: Option<String>,
+    pub total: Option<bigdecimal::BigDecimal>,
+    pub count: Option<i64>,
+    pub refund_reason: Option<String>,
+    pub refund_error_message: Option<String>,
+    #[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>,
+}
+
+pub trait RefundDistributionAnalytics: LoadRow<RefundDistributionRow> {}
+
+#[async_trait::async_trait]
+pub trait RefundDistribution<T>
+where
+    T: AnalyticsDataSource + RefundDistributionAnalytics,
+{
+    #[allow(clippy::too_many_arguments)]
+    async fn load_distribution(
+        &self,
+        distribution: &RefundDistributionBody,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>>;
+}
+
+#[async_trait::async_trait]
+impl<T> RefundDistribution<T> for RefundDistributions
+where
+    T: AnalyticsDataSource + RefundDistributionAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+    Window<&'static str>: ToSql<T>,
+{
+    async fn load_distribution(
+        &self,
+        distribution: &RefundDistributionBody,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>> {
+        match self {
+            Self::SessionizedRefundReason => {
+                sessionized_distribution::RefundReason
+                    .load_distribution(
+                        distribution,
+                        dimensions,
+                        auth,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::SessionizedRefundErrorMessage => {
+                sessionized_distribution::RefundErrorMessage
+                    .load_distribution(
+                        distribution,
+                        dimensions,
+                        auth,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+        }
+    }
+}
diff --git a/crates/analytics/src/refunds/distribution/sessionized_distribution.rs b/crates/analytics/src/refunds/distribution/sessionized_distribution.rs
new file mode 100644
index 00000000000..391b855e96e
--- /dev/null
+++ b/crates/analytics/src/refunds/distribution/sessionized_distribution.rs
@@ -0,0 +1,7 @@
+mod refund_error_message;
+mod refund_reason;
+
+pub(super) use refund_error_message::RefundErrorMessage;
+pub(super) use refund_reason::RefundReason;
+
+pub use super::{RefundDistribution, RefundDistributionAnalytics, RefundDistributionRow};
diff --git a/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_error_message.rs b/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_error_message.rs
new file mode 100644
index 00000000000..a4268c86cbe
--- /dev/null
+++ b/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_error_message.rs
@@ -0,0 +1,177 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, RefundDistributionBody, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use diesel_models::enums as storage_enums;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::{RefundDistribution, RefundDistributionRow};
+use crate::{
+    enums::AuthInfo,
+    query::{
+        Aggregate, GroupByClause, Order, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window,
+    },
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(crate) struct RefundErrorMessage;
+
+#[async_trait::async_trait]
+impl<T> RefundDistribution<T> for RefundErrorMessage
+where
+    T: AnalyticsDataSource + super::RefundDistributionAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+    Window<&'static str>: ToSql<T>,
+{
+    async fn load_distribution(
+        &self,
+        distribution: &RefundDistributionBody,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>> {
+        let mut query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(&distribution.distribution_for)
+            .switch()?;
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        auth.set_filter_clause(&mut query_builder).switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        query_builder
+            .add_filter_clause(
+                RefundDimensions::RefundStatus,
+                storage_enums::RefundStatus::Failure,
+            )
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        query_builder
+            .add_group_by_clause(&distribution.distribution_for)
+            .attach_printable("Error grouping by distribution_for")
+            .switch()?;
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        for dim in dimensions.iter() {
+            query_builder.add_outer_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_outer_select_column(&distribution.distribution_for)
+            .switch()?;
+        query_builder.add_outer_select_column("count").switch()?;
+        query_builder
+            .add_outer_select_column("start_bucket")
+            .switch()?;
+        query_builder
+            .add_outer_select_column("end_bucket")
+            .switch()?;
+        let sql_dimensions = query_builder.transform_to_sql_values(dimensions).switch()?;
+
+        query_builder
+            .add_outer_select_column(Window::Sum {
+                field: "count",
+                partition_by: Some(sql_dimensions),
+                order_by: None,
+                alias: Some("total"),
+            })
+            .switch()?;
+
+        query_builder
+            .add_top_n_clause(
+                dimensions,
+                distribution.distribution_cardinality.into(),
+                "count",
+                Order::Descending,
+            )
+            .switch()?;
+
+        query_builder
+            .execute_query::<RefundDistributionRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        i.refund_status.as_ref().map(|i| i.0.to_string()),
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>,
+                crate::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_reason.rs b/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_reason.rs
new file mode 100644
index 00000000000..a2a933db8cb
--- /dev/null
+++ b/crates/analytics/src/refunds/distribution/sessionized_distribution/refund_reason.rs
@@ -0,0 +1,169 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, RefundDistributionBody, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::{RefundDistribution, RefundDistributionRow};
+use crate::{
+    enums::AuthInfo,
+    query::{
+        Aggregate, GroupByClause, Order, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window,
+    },
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(crate) struct RefundReason;
+
+#[async_trait::async_trait]
+impl<T> RefundDistribution<T> for RefundReason
+where
+    T: AnalyticsDataSource + super::RefundDistributionAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+    Window<&'static str>: ToSql<T>,
+{
+    async fn load_distribution(
+        &self,
+        distribution: &RefundDistributionBody,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>> {
+        let mut query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(&distribution.distribution_for)
+            .switch()?;
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        auth.set_filter_clause(&mut query_builder).switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        query_builder
+            .add_group_by_clause(&distribution.distribution_for)
+            .attach_printable("Error grouping by distribution_for")
+            .switch()?;
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        for dim in dimensions.iter() {
+            query_builder.add_outer_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_outer_select_column(&distribution.distribution_for)
+            .switch()?;
+        query_builder.add_outer_select_column("count").switch()?;
+        query_builder
+            .add_outer_select_column("start_bucket")
+            .switch()?;
+        query_builder
+            .add_outer_select_column("end_bucket")
+            .switch()?;
+        let sql_dimensions = query_builder.transform_to_sql_values(dimensions).switch()?;
+
+        query_builder
+            .add_outer_select_column(Window::Sum {
+                field: "count",
+                partition_by: Some(sql_dimensions),
+                order_by: None,
+                alias: Some("total"),
+            })
+            .switch()?;
+
+        query_builder
+            .add_top_n_clause(
+                dimensions,
+                distribution.distribution_cardinality.into(),
+                "count",
+                Order::Descending,
+            )
+            .switch()?;
+
+        query_builder
+            .execute_query::<RefundDistributionRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        i.refund_status.as_ref().map(|i| i.0.to_string()),
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(RefundMetricsBucketIdentifier, RefundDistributionRow)>,
+                crate::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/analytics/src/refunds/filters.rs b/crates/analytics/src/refunds/filters.rs
index d87a778ebf3..b742187c4e6 100644
--- a/crates/analytics/src/refunds/filters.rs
+++ b/crates/analytics/src/refunds/filters.rs
@@ -56,4 +56,6 @@ pub struct RefundFilterRow {
     pub connector: Option<String>,
     pub refund_type: Option<DBEnumWrapper<RefundType>>,
     pub profile_id: Option<String>,
+    pub refund_reason: Option<String>,
+    pub refund_error_message: Option<String>,
 }
diff --git a/crates/analytics/src/refunds/metrics.rs b/crates/analytics/src/refunds/metrics.rs
index c211ea82d7a..57e6511d92c 100644
--- a/crates/analytics/src/refunds/metrics.rs
+++ b/crates/analytics/src/refunds/metrics.rs
@@ -31,6 +31,8 @@ pub struct RefundMetricRow {
     pub connector: Option<String>,
     pub refund_type: Option<DBEnumWrapper<RefundType>>,
     pub profile_id: Option<String>,
+    pub refund_reason: Option<String>,
+    pub refund_error_message: Option<String>,
     pub total: Option<bigdecimal::BigDecimal>,
     pub count: Option<i64>,
     #[serde(with = "common_utils::custom_serde::iso8601::option")]
@@ -122,6 +124,16 @@ where
                     .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                     .await
             }
+            Self::SessionizedRefundReason => {
+                sessionized_metrics::RefundReason
+                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
+                    .await
+            }
+            Self::SessionizedRefundErrorMessage => {
+                sessionized_metrics::RefundErrorMessage
+                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
+                    .await
+            }
         }
     }
 }
diff --git a/crates/analytics/src/refunds/metrics/refund_count.rs b/crates/analytics/src/refunds/metrics/refund_count.rs
index 07de04c5898..7079993094d 100644
--- a/crates/analytics/src/refunds/metrics/refund_count.rs
+++ b/crates/analytics/src/refunds/metrics/refund_count.rs
@@ -99,6 +99,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/refund_processed_amount.rs b/crates/analytics/src/refunds/metrics/refund_processed_amount.rs
index 6cba5f58fed..3890b8be6e9 100644
--- a/crates/analytics/src/refunds/metrics/refund_processed_amount.rs
+++ b/crates/analytics/src/refunds/metrics/refund_processed_amount.rs
@@ -107,6 +107,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/refund_success_count.rs b/crates/analytics/src/refunds/metrics/refund_success_count.rs
index 642cf70580d..4c3f600b05c 100644
--- a/crates/analytics/src/refunds/metrics/refund_success_count.rs
+++ b/crates/analytics/src/refunds/metrics/refund_success_count.rs
@@ -102,6 +102,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/refund_success_rate.rs b/crates/analytics/src/refunds/metrics/refund_success_rate.rs
index 7b5716ba41a..8ed144999a7 100644
--- a/crates/analytics/src/refunds/metrics/refund_success_rate.rs
+++ b/crates/analytics/src/refunds/metrics/refund_success_rate.rs
@@ -97,6 +97,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics.rs
index bb404cd3410..3a5195be6c9 100644
--- a/crates/analytics/src/refunds/metrics/sessionized_metrics.rs
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics.rs
@@ -1,10 +1,14 @@
 mod refund_count;
+mod refund_error_message;
 mod refund_processed_amount;
+mod refund_reason;
 mod refund_success_count;
 mod refund_success_rate;
 
 pub(super) use refund_count::RefundCount;
+pub(super) use refund_error_message::RefundErrorMessage;
 pub(super) use refund_processed_amount::RefundProcessedAmount;
+pub(super) use refund_reason::RefundReason;
 pub(super) use refund_success_count::RefundSuccessCount;
 pub(super) use refund_success_rate::RefundSuccessRate;
 
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_count.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_count.rs
index c77e1f7a52c..20989daca7d 100644
--- a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_count.rs
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_count.rs
@@ -100,6 +100,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_error_message.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_error_message.rs
new file mode 100644
index 00000000000..72e32907efb
--- /dev/null
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_error_message.rs
@@ -0,0 +1,190 @@
+use std::collections::HashSet;
+
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use diesel_models::enums as storage_enums;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::{
+    enums::AuthInfo,
+    query::{
+        Aggregate, FilterTypes, GroupByClause, Order, QueryBuilder, QueryFilter, SeriesBucket,
+        ToSql, Window,
+    },
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(crate) struct RefundErrorMessage;
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundErrorMessage
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+    Window<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
+        let mut inner_query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+        inner_query_builder
+            .add_select_column("sum(sign_flag)")
+            .switch()?;
+
+        inner_query_builder
+            .add_custom_filter_clause(
+                RefundDimensions::RefundErrorMessage,
+                "NULL",
+                FilterTypes::IsNotNull,
+            )
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut inner_query_builder)
+            .attach_printable("Error filtering time range for inner query")
+            .switch()?;
+
+        let inner_query_string = inner_query_builder
+            .build_query()
+            .attach_printable("Error building inner query")
+            .change_context(MetricsError::QueryBuildingError)?;
+
+        let mut outer_query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+
+        for dim in dimensions.iter() {
+            outer_query_builder.add_select_column(dim).switch()?;
+        }
+
+        outer_query_builder
+            .add_select_column("sum(sign_flag) AS count")
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(format!("({}) AS total", inner_query_string))
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters
+            .set_filter_clause(&mut outer_query_builder)
+            .switch()?;
+
+        auth.set_filter_clause(&mut outer_query_builder).switch()?;
+
+        time_range
+            .set_filter_clause(&mut outer_query_builder)
+            .attach_printable("Error filtering time range for outer query")
+            .switch()?;
+
+        outer_query_builder
+            .add_filter_clause(
+                RefundDimensions::RefundStatus,
+                storage_enums::RefundStatus::Failure,
+            )
+            .switch()?;
+
+        outer_query_builder
+            .add_custom_filter_clause(
+                RefundDimensions::RefundErrorMessage,
+                "NULL",
+                FilterTypes::IsNotNull,
+            )
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            outer_query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut outer_query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        outer_query_builder
+            .add_order_by_clause("count", Order::Descending)
+            .attach_printable("Error adding order by clause")
+            .switch()?;
+
+        let filtered_dimensions: Vec<&RefundDimensions> = dimensions
+            .iter()
+            .filter(|&&dim| dim != RefundDimensions::RefundErrorMessage)
+            .collect();
+
+        for dim in &filtered_dimensions {
+            outer_query_builder
+                .add_order_by_clause(*dim, Order::Ascending)
+                .attach_printable("Error adding order by clause")
+                .switch()?;
+        }
+
+        outer_query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>,
+                crate::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_processed_amount.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_processed_amount.rs
index c91938228af..93880824ef9 100644
--- a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_processed_amount.rs
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_processed_amount.rs
@@ -47,6 +47,12 @@ where
             query_builder.add_select_column(dim).switch()?;
         }
 
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
         query_builder
             .add_select_column(Aggregate::Sum {
                 field: "refund_amount",
@@ -109,6 +115,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_reason.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_reason.rs
new file mode 100644
index 00000000000..0df28901e8f
--- /dev/null
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_reason.rs
@@ -0,0 +1,182 @@
+use std::collections::HashSet;
+
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::{
+    enums::AuthInfo,
+    query::{
+        Aggregate, FilterTypes, GroupByClause, Order, QueryBuilder, QueryFilter, SeriesBucket,
+        ToSql, Window,
+    },
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(crate) struct RefundReason;
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundReason
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+    Window<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        auth: &AuthInfo,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
+        let mut inner_query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+        inner_query_builder
+            .add_select_column("sum(sign_flag)")
+            .switch()?;
+
+        inner_query_builder
+            .add_custom_filter_clause(
+                RefundDimensions::RefundReason,
+                "NULL",
+                FilterTypes::IsNotNull,
+            )
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut inner_query_builder)
+            .attach_printable("Error filtering time range for inner query")
+            .switch()?;
+
+        let inner_query_string = inner_query_builder
+            .build_query()
+            .attach_printable("Error building inner query")
+            .change_context(MetricsError::QueryBuildingError)?;
+
+        let mut outer_query_builder: QueryBuilder<T> =
+            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
+
+        for dim in dimensions.iter() {
+            outer_query_builder.add_select_column(dim).switch()?;
+        }
+
+        outer_query_builder
+            .add_select_column("sum(sign_flag) AS count")
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(format!("({}) AS total", inner_query_string))
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+
+        outer_query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters
+            .set_filter_clause(&mut outer_query_builder)
+            .switch()?;
+
+        auth.set_filter_clause(&mut outer_query_builder).switch()?;
+
+        time_range
+            .set_filter_clause(&mut outer_query_builder)
+            .attach_printable("Error filtering time range for outer query")
+            .switch()?;
+
+        outer_query_builder
+            .add_custom_filter_clause(
+                RefundDimensions::RefundReason,
+                "NULL",
+                FilterTypes::IsNotNull,
+            )
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            outer_query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut outer_query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        outer_query_builder
+            .add_order_by_clause("count", Order::Descending)
+            .attach_printable("Error adding order by clause")
+            .switch()?;
+
+        let filtered_dimensions: Vec<&RefundDimensions> = dimensions
+            .iter()
+            .filter(|&&dim| dim != RefundDimensions::RefundReason)
+            .collect();
+
+        for dim in &filtered_dimensions {
+            outer_query_builder
+                .add_order_by_clause(*dim, Order::Ascending)
+                .attach_printable("Error adding order by clause")
+                .switch()?;
+        }
+
+        outer_query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>,
+                crate::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_count.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_count.rs
index 332261a3208..c0bb139c46f 100644
--- a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_count.rs
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_count.rs
@@ -102,6 +102,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_rate.rs b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_rate.rs
index 35ee0d61b50..e2348d51ad7 100644
--- a/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_rate.rs
+++ b/crates/analytics/src/refunds/metrics/sessionized_metrics/refund_success_rate.rs
@@ -97,6 +97,8 @@ where
                         i.connector.clone(),
                         i.refund_type.as_ref().map(|i| i.0.to_string()),
                         i.profile_id.clone(),
+                        i.refund_reason.clone(),
+                        i.refund_error_message.clone(),
                         TimeRange {
                             start_time: match (granularity, i.start_bucket) {
                                 (Some(g), Some(st)) => g.clip_to_start(st)?,
diff --git a/crates/analytics/src/refunds/types.rs b/crates/analytics/src/refunds/types.rs
index 3f22081a69d..c0735557d1c 100644
--- a/crates/analytics/src/refunds/types.rs
+++ b/crates/analytics/src/refunds/types.rs
@@ -42,6 +42,21 @@ where
                 .attach_printable("Error adding profile id filter")?;
         }
 
+        if !self.refund_reason.is_empty() {
+            builder
+                .add_filter_in_range_clause(RefundDimensions::RefundReason, &self.refund_reason)
+                .attach_printable("Error adding refund reason filter")?;
+        }
+
+        if !self.refund_error_message.is_empty() {
+            builder
+                .add_filter_in_range_clause(
+                    RefundDimensions::RefundErrorMessage,
+                    &self.refund_error_message,
+                )
+                .attach_printable("Error adding refund error message filter")?;
+        }
+
         Ok(())
     }
 }
diff --git a/crates/analytics/src/sqlx.rs b/crates/analytics/src/sqlx.rs
index 1d91ce17c6a..2a94d528768 100644
--- a/crates/analytics/src/sqlx.rs
+++ b/crates/analytics/src/sqlx.rs
@@ -154,6 +154,7 @@ impl super::payment_intents::filters::PaymentIntentFilterAnalytics for SqlxClien
 impl super::payment_intents::metrics::PaymentIntentMetricAnalytics for SqlxClient {}
 impl super::refunds::metrics::RefundMetricAnalytics for SqlxClient {}
 impl super::refunds::filters::RefundFilterAnalytics for SqlxClient {}
+impl super::refunds::distribution::RefundDistributionAnalytics for SqlxClient {}
 impl super::disputes::filters::DisputeFilterAnalytics for SqlxClient {}
 impl super::disputes::metrics::DisputeMetricAnalytics for SqlxClient {}
 impl super::frm::metrics::FrmMetricAnalytics for SqlxClient {}
@@ -214,6 +215,15 @@ impl<'a> FromRow<'a, PgRow> for super::refunds::metrics::RefundMetricRow {
             ColumnNotFound(_) => Ok(Default::default()),
             e => Err(e),
         })?;
+        let refund_reason: Option<String> = row.try_get("refund_reason").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_error_message: Option<String> =
+            row.try_get("refund_error_message").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
         let total: Option<bigdecimal::BigDecimal> = row.try_get("total").or_else(|e| match e {
             ColumnNotFound(_) => Ok(Default::default()),
             e => Err(e),
@@ -235,6 +245,8 @@ impl<'a> FromRow<'a, PgRow> for super::refunds::metrics::RefundMetricRow {
             connector,
             refund_type,
             profile_id,
+            refund_reason,
+            refund_error_message,
             total,
             count,
             start_bucket,
@@ -791,12 +803,88 @@ impl<'a> FromRow<'a, PgRow> for super::refunds::filters::RefundFilterRow {
             ColumnNotFound(_) => Ok(Default::default()),
             e => Err(e),
         })?;
+        let refund_reason: Option<String> = row.try_get("refund_reason").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_error_message: Option<String> =
+            row.try_get("refund_error_message").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
         Ok(Self {
             currency,
             refund_status,
             connector,
             refund_type,
             profile_id,
+            refund_reason,
+            refund_error_message,
+        })
+    }
+}
+
+impl<'a> FromRow<'a, PgRow> for super::refunds::distribution::RefundDistributionRow {
+    fn from_row(row: &'a PgRow) -> sqlx::Result<Self> {
+        let currency: Option<DBEnumWrapper<Currency>> =
+            row.try_get("currency").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let refund_status: Option<DBEnumWrapper<RefundStatus>> =
+            row.try_get("refund_status").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let connector: Option<String> = row.try_get("connector").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_type: Option<DBEnumWrapper<RefundType>> =
+            row.try_get("refund_type").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let profile_id: Option<String> = row.try_get("profile_id").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let total: Option<bigdecimal::BigDecimal> = row.try_get("total").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let count: Option<i64> = row.try_get("count").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_reason: Option<String> = row.try_get("refund_reason").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_error_message: Option<String> =
+            row.try_get("refund_error_message").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        // Removing millisecond precision to get accurate diffs against clickhouse
+        let start_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("start_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        let end_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("end_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        Ok(Self {
+            currency,
+            refund_status,
+            connector,
+            refund_type,
+            profile_id,
+            total,
+            count,
+            refund_reason,
+            refund_error_message,
+            start_bucket,
+            end_bucket,
         })
     }
 }
diff --git a/crates/api_models/src/analytics.rs b/crates/api_models/src/analytics.rs
index b6d4044c5f3..806eb4b6e0e 100644
--- a/crates/api_models/src/analytics.rs
+++ b/crates/api_models/src/analytics.rs
@@ -12,7 +12,7 @@ use self::{
     frm::{FrmDimensions, FrmMetrics},
     payment_intents::{PaymentIntentDimensions, PaymentIntentMetrics},
     payments::{PaymentDimensions, PaymentDistributions, PaymentMetrics},
-    refunds::{RefundDimensions, RefundMetrics},
+    refunds::{RefundDimensions, RefundDistributions, RefundMetrics},
     sdk_events::{SdkEventDimensions, SdkEventMetrics},
 };
 pub mod active_payments;
@@ -73,7 +73,7 @@ pub struct GetPaymentMetricRequest {
     #[serde(default)]
     pub filters: payments::PaymentFilters,
     pub metrics: HashSet<PaymentMetrics>,
-    pub distribution: Option<Distribution>,
+    pub distribution: Option<PaymentDistributionBody>,
     #[serde(default)]
     pub delta: bool,
 }
@@ -98,11 +98,18 @@ impl Into<u64> for QueryLimit {
 
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "camelCase")]
-pub struct Distribution {
+pub struct PaymentDistributionBody {
     pub distribution_for: PaymentDistributions,
     pub distribution_cardinality: QueryLimit,
 }
 
+#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RefundDistributionBody {
+    pub distribution_for: RefundDistributions,
+    pub distribution_cardinality: QueryLimit,
+}
+
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ReportRequest {
@@ -142,6 +149,7 @@ pub struct GetRefundMetricRequest {
     #[serde(default)]
     pub filters: refunds::RefundFilters,
     pub metrics: HashSet<RefundMetrics>,
+    pub distribution: Option<RefundDistributionBody>,
     #[serde(default)]
     pub delta: bool,
 }
@@ -230,8 +238,12 @@ pub struct PaymentIntentsAnalyticsMetadata {
 
 #[derive(Debug, serde::Serialize)]
 pub struct RefundsAnalyticsMetadata {
+    pub total_refund_success_rate: Option<f64>,
     pub total_refund_processed_amount: Option<u64>,
     pub total_refund_processed_amount_in_usd: Option<u64>,
+    pub total_refund_processed_count: Option<u64>,
+    pub total_refund_reason_count: Option<u64>,
+    pub total_refund_error_message_count: Option<u64>,
 }
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "camelCase")]
diff --git a/crates/api_models/src/analytics/refunds.rs b/crates/api_models/src/analytics/refunds.rs
index d981bd4382f..0afca6c1ef6 100644
--- a/crates/api_models/src/analytics/refunds.rs
+++ b/crates/api_models/src/analytics/refunds.rs
@@ -43,6 +43,10 @@ pub struct RefundFilters {
     pub refund_type: Vec<RefundType>,
     #[serde(default)]
     pub profile_id: Vec<id_type::ProfileId>,
+    #[serde(default)]
+    pub refund_reason: Vec<String>,
+    #[serde(default)]
+    pub refund_error_message: Vec<String>,
 }
 
 #[derive(
@@ -67,6 +71,8 @@ pub enum RefundDimensions {
     Connector,
     RefundType,
     ProfileId,
+    RefundReason,
+    RefundErrorMessage,
 }
 
 #[derive(
@@ -92,6 +98,44 @@ pub enum RefundMetrics {
     SessionizedRefundCount,
     SessionizedRefundSuccessCount,
     SessionizedRefundProcessedAmount,
+    SessionizedRefundReason,
+    SessionizedRefundErrorMessage,
+}
+
+#[derive(Debug, Default, serde::Serialize)]
+pub struct ReasonsResult {
+    pub reason: String,
+    pub count: i64,
+    pub percentage: f64,
+}
+
+#[derive(Debug, Default, serde::Serialize)]
+pub struct ErrorMessagesResult {
+    pub error_message: String,
+    pub count: i64,
+    pub percentage: f64,
+}
+
+#[derive(
+    Clone,
+    Copy,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumIter,
+    strum::AsRefStr,
+)]
+#[strum(serialize_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
+pub enum RefundDistributions {
+    #[strum(serialize = "refund_reason")]
+    SessionizedRefundReason,
+    #[strum(serialize = "refund_error_message")]
+    SessionizedRefundErrorMessage,
 }
 
 pub mod metric_behaviour {
@@ -124,9 +168,10 @@ pub struct RefundMetricsBucketIdentifier {
     pub currency: Option<Currency>,
     pub refund_status: Option<String>,
     pub connector: Option<String>,
-
     pub refund_type: Option<String>,
     pub profile_id: Option<String>,
+    pub refund_reason: Option<String>,
+    pub refund_error_message: Option<String>,
     #[serde(rename = "time_range")]
     pub time_bucket: TimeRange,
     #[serde(rename = "time_bucket")]
@@ -141,6 +186,8 @@ impl Hash for RefundMetricsBucketIdentifier {
         self.connector.hash(state);
         self.refund_type.hash(state);
         self.profile_id.hash(state);
+        self.refund_reason.hash(state);
+        self.refund_error_message.hash(state);
         self.time_bucket.hash(state);
     }
 }
@@ -155,12 +202,15 @@ impl PartialEq for RefundMetricsBucketIdentifier {
 }
 
 impl RefundMetricsBucketIdentifier {
+    #[allow(clippy::too_many_arguments)]
     pub fn new(
         currency: Option<Currency>,
         refund_status: Option<String>,
         connector: Option<String>,
         refund_type: Option<String>,
         profile_id: Option<String>,
+        refund_reason: Option<String>,
+        refund_error_message: Option<String>,
         normalized_time_range: TimeRange,
     ) -> Self {
         Self {
@@ -169,6 +219,8 @@ impl RefundMetricsBucketIdentifier {
             connector,
             refund_type,
             profile_id,
+            refund_reason,
+            refund_error_message,
             time_bucket: normalized_time_range,
             start_time: normalized_time_range.start_time,
         }
@@ -176,11 +228,18 @@ impl RefundMetricsBucketIdentifier {
 }
 #[derive(Debug, serde::Serialize)]
 pub struct RefundMetricsBucketValue {
+    pub successful_refunds: Option<u32>,
+    pub total_refunds: Option<u32>,
     pub refund_success_rate: Option<f64>,
     pub refund_count: Option<u64>,
     pub refund_success_count: Option<u64>,
     pub refund_processed_amount: Option<u64>,
     pub refund_processed_amount_in_usd: Option<u64>,
+    pub refund_processed_count: Option<u64>,
+    pub refund_reason_distribution: Option<Vec<ReasonsResult>>,
+    pub refund_error_message_distribution: Option<Vec<ErrorMessagesResult>>,
+    pub refund_reason_count: Option<u64>,
+    pub refund_error_message_count: Option<u64>,
 }
 #[derive(Debug, serde::Serialize)]
 pub struct RefundMetricsBucketResponse {

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
Adding metrics, and support for Refund Page in Analytics V2 Dashboard through sessionizer.

The metrics added are as follows:
- **Static Metrics in overview section:**
  - Refund Success Rate
  - Total Refunds Processed (Amount)
  - Successful Refunds
  - Failed Refunds
  - Pending Refunds
- **Series Graphs:**
  - Refunds Processed (Amount and Count) (With granularity)
  - Refunds Success Rate (With granularity)
- **Distributions:**
  - Successful Refunds by connector
  - Failed Refunds by connector
- **Tables**
  - Refund Reasons
  - Failed Refund Error Message
  - Failed Refund Error Reasons


This PR also adds support for refunds distribution, similar to payments distribution, which may be needed in the future for more advanced analytics.
The following distributions are added:
- Refund Reasons
- Refund Error Message


### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
Provide more insights into Refunds data for the merchants to make important business decisions

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
Refunds Success Rate:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_success_rate"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": 6,
            "total_refunds": 10,
            "refund_success_rate": 60.0,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": 60.0,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"successful_refunds": 6,
"total_refunds": 10,
"refund_success_rate": 60.0,
```
- metaData:

```json
"total_refund_success_rate": 60.0,
```
Total Refunds Processed (Amount)

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_processed_amount"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 1800,
            "refund_processed_amount_in_usd": 21,
            "refund_processed_count": 3,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": "INR",
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 1800,
            "refund_processed_amount_in_usd": 1800,
            "refund_processed_count": 3,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": "USD",
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 3600,
            "total_refund_processed_amount_in_usd": 1821,
            "total_refund_processed_count": 6,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"refund_processed_amount": 1800,
"refund_processed_amount_in_usd": 21,
"refund_processed_count": 3,
```
- metaData:

```json
"total_refund_processed_amount": 3600,
"total_refund_processed_amount_in_usd": 1821,
"total_refund_processed_count": 6,
```
Successful Refunds:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "success"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:

```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 6,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:

- queryData:

```json
"refund_count": 6,
```

Failed Refunds

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "failure"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:

```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 4,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:

- queryData:

```json
"refund_count": 4,
```

Pending Refunds

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "pending"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 0,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:

- queryData:

```json
"refund_count": 0,
```

Refund Success Rate series graph is similar to Refund Success Rate above, granularity will be added.

Refund Processed Amount and Count series graph is similar to the one above, granularity will be added.


Successful Refunds Distribution by connector:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count",
            "sessionized_refund_success_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 7,
            "refund_success_count": 6,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 7,
"refund_success_count": 6,
"connector": "stripe_test",
```

Failed Refunds Distribution by connector:
- This will have multiple API calls from FE, and data would be calculated at FE only.
- First Request:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```


Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 7,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 7,
"connector": "stripe_test",
```

- Second Request:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "failure"
            ]
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 1,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 1,
"connector": "stripe_test",
```

From the two API calls, failed refunds and total refunds can be calculated for every connector, and the failed refunds distribution can be plotted and displayed.



Refund Reasons:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_reason"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_reason"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test REFUND - 1",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 6,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 2,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 10,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"refund_reason_count": 1,
"refund_reason": "Test Refund - 3",
"connector": "stripe_test",
```

- metaData:

```json
"total_refund_reason_count": 10,
```

Failed Refund Reasons:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_reason"
        ],
        "filters": {
            "refund_status": ["failure"]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_reason"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 2,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 4,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:
```json
"refund_reason_count": 1,
"refund_reason": "Test Refund - 3",
"connector": "adyen",
```

- metaData:
```json
"total_refund_reason_count": 4,
```


Failed Refund Error Message:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_error_message"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_error_message"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 1,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure 3.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 1,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 2
        }
    ]
}
```

Fields to be tested:
- queryData:
```json
"refund_error_message_count": 1,
"refund_error_message": "The refund failed due to test-failure.",
"connector": "adyen",
```

- metaData:

```json
"total_refund_error_message_count": 2
```


Refund Reasons Distribution:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "distribution": {
            "distributionFor": "sessionized_refund_reason",
            "distributionCardinality": "TOP_5"
        },
        "metrics": [
        ],
        "source": "BATCH",
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test REFUND - 1",
                    "count": 1,
                    "percentage": 14.29
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test REFUND - 1",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test Refund - 2",
                    "count": 2,
                    "percentage": 66.67
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test Refund - 3",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Customer returned product",
                    "count": 6,
                    "percentage": 85.71
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:

```json
"refund_reason_distribution": [
       {
            "reason": "Test REFUND - 1",
            "count": 1,
            "percentage": 14.29
        }
],
"connector": "stripe_test",
```

Refund Error Message Distribution:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "distribution": {
            "distributionFor": "sessionized_refund_error_message",
            "distributionCardinality": "TOP_5"
        },
        "metrics": [
        ],
        "source": "BATCH",
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "The refund failed due to test-failure 3.",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure 3.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "The refund failed due to test-failure.",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "",
                    "count": 1,
                    "percentage": 100.0
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:

```json
"refund_error_message_distribution": [
    {
        "error_message": "The refund failed due to test-failure 3.",
        "count": 1,
        "percentage": 33.33
    }
],
"connector": "adyen",
```
## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible


Refunds Success Rate:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_success_rate"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": 6,
            "total_refunds": 10,
            "refund_success_rate": 60.0,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": 60.0,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"successful_refunds": 6,
"total_refunds": 10,
"refund_success_rate": 60.0,
```
- metaData:

```json
"total_refund_success_rate": 60.0,
```
Total Refunds Processed (Amount)

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_processed_amount"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 1800,
            "refund_processed_amount_in_usd": 21,
            "refund_processed_count": 3,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": "INR",
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 1800,
            "refund_processed_amount_in_usd": 1800,
            "refund_processed_count": 3,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": "USD",
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 3600,
            "total_refund_processed_amount_in_usd": 1821,
            "total_refund_processed_count": 6,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"refund_processed_amount": 1800,
"refund_processed_amount_in_usd": 21,
"refund_processed_count": 3,
```
- metaData:

```json
"total_refund_processed_amount": 3600,
"total_refund_processed_amount_in_usd": 1821,
"total_refund_processed_count": 6,
```
Successful Refunds:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "success"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:

```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 6,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:

- queryData:

```json
"refund_count": 6,
```

Failed Refunds

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "failure"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:

```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 4,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:

- queryData:

```json
"refund_count": 4,
```

Pending Refunds

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjc5Mjk0OCwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.Q5ruAj8DwAp5XDj1ktFhma4aZXAHSZBmRSw_EnPk4HE' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "pending"
            ]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 0,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": null,
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:

- queryData:

```json
"refund_count": 0,
```

Refund Success Rate series graph is similar to Refund Success Rate above, granularity will be added.

Refund Processed Amount and Count series graph is similar to the one above, granularity will be added.


Successful Refunds Distribution by connector:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count",
            "sessionized_refund_success_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 7,
            "refund_success_count": 6,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 7,
"refund_success_count": 6,
"connector": "stripe_test",
```

Failed Refunds Distribution by connector:
- This will have multiple API calls from FE, and data would be calculated at FE only.
- First Request:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```


Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 7,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 7,
"connector": "stripe_test",
```

- Second Request:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "filters": {
            "refund_status": [
                "failure"
            ]
        },
        "groupByNames": [
            "connector"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_count"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 3,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": 1,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested and taken into account:
- queryData:

```json
"refund_count": 1,
"connector": "stripe_test",
```

From the two API calls, failed refunds and total refunds can be calculated for every connector, and the failed refunds distribution can be plotted and displayed.



Refund Reasons:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_reason"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_reason"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test REFUND - 1",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 6,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 2,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 10,
            "total_refund_error_message_count": 0
        }
    ]
}
```
Fields to be tested:
- queryData:

```json
"refund_reason_count": 1,
"refund_reason": "Test Refund - 3",
"connector": "stripe_test",
```

- metaData:

```json
"total_refund_reason_count": 10,
```

Failed Refund Reasons:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_reason"
        ],
        "filters": {
            "refund_status": ["failure"]
        },
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_reason"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 2,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 1,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 4,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:
```json
"refund_reason_count": 1,
"refund_reason": "Test Refund - 3",
"connector": "adyen",
```

- metaData:
```json
"total_refund_reason_count": 4,
```


Failed Refund Error Message:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector", "refund_error_message"
        ],
        "source": "BATCH",
        "metrics": [
            "sessionized_refund_error_message"
        ],
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 1,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure 3.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 1,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 2
        }
    ]
}
```

Fields to be tested:
- queryData:
```json
"refund_error_message_count": 1,
"refund_error_message": "The refund failed due to test-failure.",
"connector": "adyen",
```

- metaData:

```json
"total_refund_error_message_count": 2
```


Refund Reasons Distribution:

```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "distribution": {
            "distributionFor": "sessionized_refund_reason",
            "distributionCardinality": "TOP_5"
        },
        "metrics": [
        ],
        "source": "BATCH",
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test REFUND - 1",
                    "count": 1,
                    "percentage": 14.29
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test REFUND - 1",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test Refund - 2",
                    "count": 2,
                    "percentage": 66.67
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 2",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Test Refund - 3",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Test Refund - 3",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": [
                {
                    "reason": "Customer returned product",
                    "count": 6,
                    "percentage": 85.71
                }
            ],
            "refund_error_message_distribution": null,
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": "Customer returned product",
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:

```json
"refund_reason_distribution": [
       {
            "reason": "Test REFUND - 1",
            "count": 1,
            "percentage": 14.29
        }
],
"connector": "stripe_test",
```

Refund Error Message Distribution:
```bash
curl --location 'http://localhost:8080/analytics/v1/org/metrics/refunds' \
--header 'Accept: */*' \
--header 'Accept-Language: en-US,en;q=0.9' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/json' \
--header 'Origin: http://localhost:9000' \
--header 'Referer: http://localhost:9000/' \
--header 'Sec-Fetch-Dest: empty' \
--header 'Sec-Fetch-Mode: cors' \
--header 'Sec-Fetch-Site: same-site' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
--header 'api-key: dev_LZcIA7XeMpnK5satp4CDvjcnHCaeKTBcosyuBBJaknZu1odhFo96cwS0nSdfzuJF' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNTQ5ZTNkMmItMTY5Yi00NzUzLWJmNTQtZDcxMTM2YjRiN2JkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzI2MDQ2MzI4Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTczMjk3MjQxOSwib3JnX2lkIjoib3JnX1ZwU0hPanNZZkR2YWJWWUpnQ0FKIiwicHJvZmlsZV9pZCI6InByb192NXNGb0hlODBPZWlVbElvbm9jTSIsInRlbmFudF9pZCI6InB1YmxpYyJ9.eWEvxPl_3-C8tv5_uDfyqV8B8DDUeTK4yn-IHnIQvwY' \
--header 'sec-ch-ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "macOS"' \
--data '[
    {
        "timeRange": {
            "startTime": "2024-11-01T09:00:00Z",
            "endTime": "2024-11-29T09:30:39Z"
        },
        "groupByNames": [
            "connector"
        ],
        "distribution": {
            "distributionFor": "sessionized_refund_error_message",
            "distributionCardinality": "TOP_5"
        },
        "metrics": [
        ],
        "source": "BATCH",
        "delta": true
    }
]'
```

Response:
```json
{
    "queryData": [
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "The refund failed due to test-failure 3.",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure 3.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "The refund failed due to test-failure.",
                    "count": 1,
                    "percentage": 33.33
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "adyen",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": "The refund failed due to test-failure.",
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        },
        {
            "successful_refunds": null,
            "total_refunds": null,
            "refund_success_rate": null,
            "refund_count": null,
            "refund_success_count": null,
            "refund_processed_amount": 0,
            "refund_processed_amount_in_usd": null,
            "refund_processed_count": null,
            "refund_reason_distribution": null,
            "refund_error_message_distribution": [
                {
                    "error_message": "",
                    "count": 1,
                    "percentage": 100.0
                }
            ],
            "refund_reason_count": 0,
            "refund_error_message_count": 0,
            "currency": null,
            "refund_status": null,
            "connector": "stripe_test",
            "refund_type": null,
            "profile_id": null,
            "refund_reason": null,
            "refund_error_message": null,
            "time_range": {
                "start_time": "2024-11-01T09:00:00.000Z",
                "end_time": "2024-11-29T09:30:39.000Z"
            },
            "time_bucket": "2024-11-01 09:00:00"
        }
    ],
    "metaData": [
        {
            "total_refund_success_rate": null,
            "total_refund_processed_amount": 0,
            "total_refund_processed_amount_in_usd": 0,
            "total_refund_processed_count": 0,
            "total_refund_reason_count": 0,
            "total_refund_error_message_count": 0
        }
    ]
}
```

Fields to be tested:
- queryData:

```json
"refund_error_message_distribution": [
    {
        "error_message": "The refund failed due to test-failure 3.",
        "count": 1,
        "percentage": 33.33
    }
],
"connector": "adyen",
```
