use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, }; use common_enums::enums::{AttemptStatus, AuthenticationType, Currency, PaymentMethod}; use super::{NameDescription, TimeRange}; use crate::enums::Connector; #[derive(Clone, Debug, Default, serde::Deserialize, masking::Serialize)] pub struct PaymentFilters { #[serde(default)] pub currency: Vec, #[serde(default)] pub status: Vec, #[serde(default)] pub connector: Vec, #[serde(default)] pub auth_type: Vec, #[serde(default)] pub payment_method: Vec, } #[derive( Debug, serde::Serialize, serde::Deserialize, strum::AsRefStr, PartialEq, PartialOrd, Eq, Ord, strum::Display, strum::EnumIter, Clone, Copy, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum PaymentDimensions { // Do not change the order of these enums // Consult the Dashboard FE folks since these also affects the order of metrics on FE Connector, PaymentMethod, Currency, #[strum(serialize = "authentication_type")] #[serde(rename = "authentication_type")] AuthType, #[strum(serialize = "status")] #[serde(rename = "status")] PaymentStatus, } #[derive( Clone, 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 PaymentMetrics { PaymentSuccessRate, PaymentCount, PaymentSuccessCount, PaymentProcessedAmount, AvgTicketSize, } pub mod metric_behaviour { pub struct PaymentSuccessRate; pub struct PaymentCount; pub struct PaymentSuccessCount; pub struct PaymentProcessedAmount; pub struct AvgTicketSize; } impl From for NameDescription { fn from(value: PaymentMetrics) -> Self { Self { name: value.to_string(), desc: String::new(), } } } impl From for NameDescription { fn from(value: PaymentDimensions) -> Self { Self { name: value.to_string(), desc: String::new(), } } } #[derive(Debug, serde::Serialize, Eq)] pub struct PaymentMetricsBucketIdentifier { pub currency: Option, pub status: Option, pub connector: Option, #[serde(rename = "authentication_type")] pub auth_type: Option, pub payment_method: Option, #[serde(rename = "time_range")] pub time_bucket: TimeRange, // Coz FE sucks #[serde(rename = "time_bucket")] #[serde(with = "common_utils::custom_serde::iso8601custom")] pub start_time: time::PrimitiveDateTime, } impl PaymentMetricsBucketIdentifier { pub fn new( currency: Option, status: Option, connector: Option, auth_type: Option, payment_method: Option, normalized_time_range: TimeRange, ) -> Self { Self { currency, status, connector, auth_type, payment_method, time_bucket: normalized_time_range, start_time: normalized_time_range.start_time, } } } impl Hash for PaymentMetricsBucketIdentifier { fn hash(&self, state: &mut H) { self.currency.hash(state); self.status.map(|i| i.to_string()).hash(state); self.connector.hash(state); self.auth_type.map(|i| i.to_string()).hash(state); self.payment_method.hash(state); self.time_bucket.hash(state); } } impl PartialEq for PaymentMetricsBucketIdentifier { fn eq(&self, other: &Self) -> bool { let mut left = DefaultHasher::new(); self.hash(&mut left); let mut right = DefaultHasher::new(); other.hash(&mut right); left.finish() == right.finish() } } #[derive(Debug, serde::Serialize)] pub struct PaymentMetricsBucketValue { pub payment_success_rate: Option, pub payment_count: Option, pub payment_success_count: Option, pub payment_processed_amount: Option, pub avg_ticket_size: Option, } #[derive(Debug, serde::Serialize)] pub struct MetricsBucketResponse { #[serde(flatten)] pub values: PaymentMetricsBucketValue, #[serde(flatten)] pub dimensions: PaymentMetricsBucketIdentifier, }