mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
feat(opensearch): add amount and customer_id as filters and handle name for different indexes (#7073)
This commit is contained in:
@ -456,7 +456,7 @@ pub struct OpenSearchQueryBuilder {
|
|||||||
pub query: String,
|
pub query: String,
|
||||||
pub offset: Option<i64>,
|
pub offset: Option<i64>,
|
||||||
pub count: Option<i64>,
|
pub count: Option<i64>,
|
||||||
pub filters: Vec<(String, Vec<String>)>,
|
pub filters: Vec<(String, Vec<Value>)>,
|
||||||
pub time_range: Option<OpensearchTimeRange>,
|
pub time_range: Option<OpensearchTimeRange>,
|
||||||
search_params: Vec<AuthInfo>,
|
search_params: Vec<AuthInfo>,
|
||||||
case_sensitive_fields: HashSet<&'static str>,
|
case_sensitive_fields: HashSet<&'static str>,
|
||||||
@ -477,6 +477,8 @@ impl OpenSearchQueryBuilder {
|
|||||||
"search_tags.keyword",
|
"search_tags.keyword",
|
||||||
"card_last_4.keyword",
|
"card_last_4.keyword",
|
||||||
"payment_id.keyword",
|
"payment_id.keyword",
|
||||||
|
"amount",
|
||||||
|
"customer_id.keyword",
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,7 +494,7 @@ impl OpenSearchQueryBuilder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_filter_clause(&mut self, lhs: String, rhs: Vec<String>) -> QueryResult<()> {
|
pub fn add_filter_clause(&mut self, lhs: String, rhs: Vec<Value>) -> QueryResult<()> {
|
||||||
self.filters.push((lhs, rhs));
|
self.filters.push((lhs, rhs));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -505,9 +507,18 @@ impl OpenSearchQueryBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_amount_field(&self, index: SearchIndex) -> &str {
|
||||||
|
match index {
|
||||||
|
SearchIndex::Refunds | SearchIndex::SessionizerRefunds => "refund_amount",
|
||||||
|
SearchIndex::Disputes | SearchIndex::SessionizerDisputes => "dispute_amount",
|
||||||
|
_ => "amount",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_filter_array(
|
pub fn build_filter_array(
|
||||||
&self,
|
&self,
|
||||||
case_sensitive_filters: Vec<&(String, Vec<String>)>,
|
case_sensitive_filters: Vec<&(String, Vec<Value>)>,
|
||||||
|
index: SearchIndex,
|
||||||
) -> Vec<Value> {
|
) -> Vec<Value> {
|
||||||
let mut filter_array = Vec::new();
|
let mut filter_array = Vec::new();
|
||||||
if !self.query.is_empty() {
|
if !self.query.is_empty() {
|
||||||
@ -522,7 +533,14 @@ impl OpenSearchQueryBuilder {
|
|||||||
|
|
||||||
let case_sensitive_json_filters = case_sensitive_filters
|
let case_sensitive_json_filters = case_sensitive_filters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| json!({"terms": {k: v}}))
|
.map(|(k, v)| {
|
||||||
|
let key = if *k == "amount" {
|
||||||
|
self.get_amount_field(index).to_string()
|
||||||
|
} else {
|
||||||
|
k.clone()
|
||||||
|
};
|
||||||
|
json!({"terms": {key: v}})
|
||||||
|
})
|
||||||
.collect::<Vec<Value>>();
|
.collect::<Vec<Value>>();
|
||||||
|
|
||||||
filter_array.extend(case_sensitive_json_filters);
|
filter_array.extend(case_sensitive_json_filters);
|
||||||
@ -542,7 +560,7 @@ impl OpenSearchQueryBuilder {
|
|||||||
pub fn build_case_insensitive_filters(
|
pub fn build_case_insensitive_filters(
|
||||||
&self,
|
&self,
|
||||||
mut payload: Value,
|
mut payload: Value,
|
||||||
case_insensitive_filters: &[&(String, Vec<String>)],
|
case_insensitive_filters: &[&(String, Vec<Value>)],
|
||||||
auth_array: Vec<Value>,
|
auth_array: Vec<Value>,
|
||||||
index: SearchIndex,
|
index: SearchIndex,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
@ -690,22 +708,16 @@ impl OpenSearchQueryBuilder {
|
|||||||
/// Ensure that the input data and the structure of the query are valid and correctly handled.
|
/// Ensure that the input data and the structure of the query are valid and correctly handled.
|
||||||
pub fn construct_payload(&self, indexes: &[SearchIndex]) -> QueryResult<Vec<Value>> {
|
pub fn construct_payload(&self, indexes: &[SearchIndex]) -> QueryResult<Vec<Value>> {
|
||||||
let mut query_obj = Map::new();
|
let mut query_obj = Map::new();
|
||||||
let mut bool_obj = Map::new();
|
let bool_obj = Map::new();
|
||||||
|
|
||||||
let (case_sensitive_filters, case_insensitive_filters): (Vec<_>, Vec<_>) = self
|
let (case_sensitive_filters, case_insensitive_filters): (Vec<_>, Vec<_>) = self
|
||||||
.filters
|
.filters
|
||||||
.iter()
|
.iter()
|
||||||
.partition(|(k, _)| self.case_sensitive_fields.contains(k.as_str()));
|
.partition(|(k, _)| self.case_sensitive_fields.contains(k.as_str()));
|
||||||
|
|
||||||
let filter_array = self.build_filter_array(case_sensitive_filters);
|
|
||||||
|
|
||||||
if !filter_array.is_empty() {
|
|
||||||
bool_obj.insert("filter".to_string(), Value::Array(filter_array));
|
|
||||||
}
|
|
||||||
|
|
||||||
let should_array = self.build_auth_array();
|
let should_array = self.build_auth_array();
|
||||||
|
|
||||||
query_obj.insert("bool".to_string(), Value::Object(bool_obj));
|
query_obj.insert("bool".to_string(), Value::Object(bool_obj.clone()));
|
||||||
|
|
||||||
let mut sort_obj = Map::new();
|
let mut sort_obj = Map::new();
|
||||||
sort_obj.insert(
|
sort_obj.insert(
|
||||||
@ -724,6 +736,16 @@ impl OpenSearchQueryBuilder {
|
|||||||
Value::Object(sort_obj.clone())
|
Value::Object(sort_obj.clone())
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
let filter_array = self.build_filter_array(case_sensitive_filters.clone(), *index);
|
||||||
|
if !filter_array.is_empty() {
|
||||||
|
payload
|
||||||
|
.get_mut("query")
|
||||||
|
.and_then(|query| query.get_mut("bool"))
|
||||||
|
.and_then(|bool_obj| bool_obj.as_object_mut())
|
||||||
|
.map(|bool_map| {
|
||||||
|
bool_map.insert("filter".to_string(), Value::Array(filter_array));
|
||||||
|
});
|
||||||
|
}
|
||||||
payload = self.build_case_insensitive_filters(
|
payload = self.build_case_insensitive_filters(
|
||||||
payload,
|
payload,
|
||||||
&case_insensitive_filters,
|
&case_insensitive_filters,
|
||||||
|
|||||||
@ -5,12 +5,17 @@ use api_models::analytics::search::{
|
|||||||
use common_utils::errors::{CustomResult, ReportSwitchExt};
|
use common_utils::errors::{CustomResult, ReportSwitchExt};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use router_env::tracing;
|
use router_env::tracing;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
enums::AuthInfo,
|
enums::AuthInfo,
|
||||||
opensearch::{OpenSearchClient, OpenSearchError, OpenSearchQuery, OpenSearchQueryBuilder},
|
opensearch::{OpenSearchClient, OpenSearchError, OpenSearchQuery, OpenSearchQueryBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn convert_to_value<T: Into<Value>>(items: Vec<T>) -> Vec<Value> {
|
||||||
|
items.into_iter().map(|item| item.into()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn msearch_results(
|
pub async fn msearch_results(
|
||||||
client: &OpenSearchClient,
|
client: &OpenSearchClient,
|
||||||
req: GetGlobalSearchRequest,
|
req: GetGlobalSearchRequest,
|
||||||
@ -38,21 +43,24 @@ pub async fn msearch_results(
|
|||||||
if let Some(currency) = filters.currency {
|
if let Some(currency) = filters.currency {
|
||||||
if !currency.is_empty() {
|
if !currency.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("currency.keyword".to_string(), currency.clone())
|
.add_filter_clause("currency.keyword".to_string(), convert_to_value(currency))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(status) = filters.status {
|
if let Some(status) = filters.status {
|
||||||
if !status.is_empty() {
|
if !status.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("status.keyword".to_string(), status.clone())
|
.add_filter_clause("status.keyword".to_string(), convert_to_value(status))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(payment_method) = filters.payment_method {
|
if let Some(payment_method) = filters.payment_method {
|
||||||
if !payment_method.is_empty() {
|
if !payment_method.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("payment_method.keyword".to_string(), payment_method.clone())
|
.add_filter_clause(
|
||||||
|
"payment_method.keyword".to_string(),
|
||||||
|
convert_to_value(payment_method),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -61,15 +69,17 @@ pub async fn msearch_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"customer_email.keyword".to_string(),
|
"customer_email.keyword".to_string(),
|
||||||
customer_email
|
convert_to_value(
|
||||||
.iter()
|
customer_email
|
||||||
.filter_map(|email| {
|
.iter()
|
||||||
// TODO: Add trait based inputs instead of converting this to strings
|
.filter_map(|email| {
|
||||||
serde_json::to_value(email)
|
// TODO: Add trait based inputs instead of converting this to strings
|
||||||
.ok()
|
serde_json::to_value(email)
|
||||||
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
.ok()
|
||||||
})
|
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
||||||
.collect(),
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -79,15 +89,17 @@ pub async fn msearch_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"feature_metadata.search_tags.keyword".to_string(),
|
"feature_metadata.search_tags.keyword".to_string(),
|
||||||
search_tags
|
convert_to_value(
|
||||||
.iter()
|
search_tags
|
||||||
.filter_map(|search_tag| {
|
.iter()
|
||||||
// TODO: Add trait based inputs instead of converting this to strings
|
.filter_map(|search_tag| {
|
||||||
serde_json::to_value(search_tag)
|
// TODO: Add trait based inputs instead of converting this to strings
|
||||||
.ok()
|
serde_json::to_value(search_tag)
|
||||||
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
.ok()
|
||||||
})
|
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
||||||
.collect(),
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -95,7 +107,7 @@ pub async fn msearch_results(
|
|||||||
if let Some(connector) = filters.connector {
|
if let Some(connector) = filters.connector {
|
||||||
if !connector.is_empty() {
|
if !connector.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("connector.keyword".to_string(), connector.clone())
|
.add_filter_clause("connector.keyword".to_string(), convert_to_value(connector))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -104,7 +116,7 @@ pub async fn msearch_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"payment_method_type.keyword".to_string(),
|
"payment_method_type.keyword".to_string(),
|
||||||
payment_method_type.clone(),
|
convert_to_value(payment_method_type),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -112,21 +124,47 @@ pub async fn msearch_results(
|
|||||||
if let Some(card_network) = filters.card_network {
|
if let Some(card_network) = filters.card_network {
|
||||||
if !card_network.is_empty() {
|
if !card_network.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("card_network.keyword".to_string(), card_network.clone())
|
.add_filter_clause(
|
||||||
|
"card_network.keyword".to_string(),
|
||||||
|
convert_to_value(card_network),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(card_last_4) = filters.card_last_4 {
|
if let Some(card_last_4) = filters.card_last_4 {
|
||||||
if !card_last_4.is_empty() {
|
if !card_last_4.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("card_last_4.keyword".to_string(), card_last_4.clone())
|
.add_filter_clause(
|
||||||
|
"card_last_4.keyword".to_string(),
|
||||||
|
convert_to_value(card_last_4),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(payment_id) = filters.payment_id {
|
if let Some(payment_id) = filters.payment_id {
|
||||||
if !payment_id.is_empty() {
|
if !payment_id.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("payment_id.keyword".to_string(), payment_id.clone())
|
.add_filter_clause(
|
||||||
|
"payment_id.keyword".to_string(),
|
||||||
|
convert_to_value(payment_id),
|
||||||
|
)
|
||||||
|
.switch()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(amount) = filters.amount {
|
||||||
|
if !amount.is_empty() {
|
||||||
|
query_builder
|
||||||
|
.add_filter_clause("amount".to_string(), convert_to_value(amount))
|
||||||
|
.switch()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(customer_id) = filters.customer_id {
|
||||||
|
if !customer_id.is_empty() {
|
||||||
|
query_builder
|
||||||
|
.add_filter_clause(
|
||||||
|
"customer_id.keyword".to_string(),
|
||||||
|
convert_to_value(customer_id),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -211,21 +249,24 @@ pub async fn search_results(
|
|||||||
if let Some(currency) = filters.currency {
|
if let Some(currency) = filters.currency {
|
||||||
if !currency.is_empty() {
|
if !currency.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("currency.keyword".to_string(), currency.clone())
|
.add_filter_clause("currency.keyword".to_string(), convert_to_value(currency))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(status) = filters.status {
|
if let Some(status) = filters.status {
|
||||||
if !status.is_empty() {
|
if !status.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("status.keyword".to_string(), status.clone())
|
.add_filter_clause("status.keyword".to_string(), convert_to_value(status))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(payment_method) = filters.payment_method {
|
if let Some(payment_method) = filters.payment_method {
|
||||||
if !payment_method.is_empty() {
|
if !payment_method.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("payment_method.keyword".to_string(), payment_method.clone())
|
.add_filter_clause(
|
||||||
|
"payment_method.keyword".to_string(),
|
||||||
|
convert_to_value(payment_method),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -234,15 +275,17 @@ pub async fn search_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"customer_email.keyword".to_string(),
|
"customer_email.keyword".to_string(),
|
||||||
customer_email
|
convert_to_value(
|
||||||
.iter()
|
customer_email
|
||||||
.filter_map(|email| {
|
.iter()
|
||||||
// TODO: Add trait based inputs instead of converting this to strings
|
.filter_map(|email| {
|
||||||
serde_json::to_value(email)
|
// TODO: Add trait based inputs instead of converting this to strings
|
||||||
.ok()
|
serde_json::to_value(email)
|
||||||
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
.ok()
|
||||||
})
|
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
||||||
.collect(),
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -252,15 +295,17 @@ pub async fn search_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"feature_metadata.search_tags.keyword".to_string(),
|
"feature_metadata.search_tags.keyword".to_string(),
|
||||||
search_tags
|
convert_to_value(
|
||||||
.iter()
|
search_tags
|
||||||
.filter_map(|search_tag| {
|
.iter()
|
||||||
// TODO: Add trait based inputs instead of converting this to strings
|
.filter_map(|search_tag| {
|
||||||
serde_json::to_value(search_tag)
|
// TODO: Add trait based inputs instead of converting this to strings
|
||||||
.ok()
|
serde_json::to_value(search_tag)
|
||||||
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
.ok()
|
||||||
})
|
.and_then(|a| a.as_str().map(|a| a.to_string()))
|
||||||
.collect(),
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -268,7 +313,7 @@ pub async fn search_results(
|
|||||||
if let Some(connector) = filters.connector {
|
if let Some(connector) = filters.connector {
|
||||||
if !connector.is_empty() {
|
if !connector.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("connector.keyword".to_string(), connector.clone())
|
.add_filter_clause("connector.keyword".to_string(), convert_to_value(connector))
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -277,7 +322,7 @@ pub async fn search_results(
|
|||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause(
|
.add_filter_clause(
|
||||||
"payment_method_type.keyword".to_string(),
|
"payment_method_type.keyword".to_string(),
|
||||||
payment_method_type.clone(),
|
convert_to_value(payment_method_type),
|
||||||
)
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
@ -285,21 +330,47 @@ pub async fn search_results(
|
|||||||
if let Some(card_network) = filters.card_network {
|
if let Some(card_network) = filters.card_network {
|
||||||
if !card_network.is_empty() {
|
if !card_network.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("card_network.keyword".to_string(), card_network.clone())
|
.add_filter_clause(
|
||||||
|
"card_network.keyword".to_string(),
|
||||||
|
convert_to_value(card_network),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(card_last_4) = filters.card_last_4 {
|
if let Some(card_last_4) = filters.card_last_4 {
|
||||||
if !card_last_4.is_empty() {
|
if !card_last_4.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("card_last_4.keyword".to_string(), card_last_4.clone())
|
.add_filter_clause(
|
||||||
|
"card_last_4.keyword".to_string(),
|
||||||
|
convert_to_value(card_last_4),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(payment_id) = filters.payment_id {
|
if let Some(payment_id) = filters.payment_id {
|
||||||
if !payment_id.is_empty() {
|
if !payment_id.is_empty() {
|
||||||
query_builder
|
query_builder
|
||||||
.add_filter_clause("payment_id.keyword".to_string(), payment_id.clone())
|
.add_filter_clause(
|
||||||
|
"payment_id.keyword".to_string(),
|
||||||
|
convert_to_value(payment_id),
|
||||||
|
)
|
||||||
|
.switch()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(amount) = filters.amount {
|
||||||
|
if !amount.is_empty() {
|
||||||
|
query_builder
|
||||||
|
.add_filter_clause("amount".to_string(), convert_to_value(amount))
|
||||||
|
.switch()?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(customer_id) = filters.customer_id {
|
||||||
|
if !customer_id.is_empty() {
|
||||||
|
query_builder
|
||||||
|
.add_filter_clause(
|
||||||
|
"customer_id.keyword".to_string(),
|
||||||
|
convert_to_value(customer_id),
|
||||||
|
)
|
||||||
.switch()?;
|
.switch()?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,8 @@ pub struct SearchFilters {
|
|||||||
pub card_network: Option<Vec<String>>,
|
pub card_network: Option<Vec<String>>,
|
||||||
pub card_last_4: Option<Vec<String>>,
|
pub card_last_4: Option<Vec<String>>,
|
||||||
pub payment_id: Option<Vec<String>>,
|
pub payment_id: Option<Vec<String>>,
|
||||||
|
pub amount: Option<Vec<u64>>,
|
||||||
|
pub customer_id: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
impl SearchFilters {
|
impl SearchFilters {
|
||||||
pub fn is_all_none(&self) -> bool {
|
pub fn is_all_none(&self) -> bool {
|
||||||
@ -27,6 +29,8 @@ impl SearchFilters {
|
|||||||
&& self.card_network.is_none()
|
&& self.card_network.is_none()
|
||||||
&& self.card_last_4.is_none()
|
&& self.card_last_4.is_none()
|
||||||
&& self.payment_id.is_none()
|
&& self.payment_id.is_none()
|
||||||
|
&& self.amount.is_none()
|
||||||
|
&& self.customer_id.is_none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user