File: crates/analytics/src/routing_events/events.rs
 Public functions: 1
 Public structs: 1

use api_models::analytics::{routing_events::RoutingEventsRequest, Granularity};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use crate::{
    query::{Aggregate, GroupByClause, QueryBuilder, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, FiltersError, FiltersResult, LoadRow},
};
pub trait RoutingEventLogAnalytics: LoadRow<RoutingEventsResult> {}

pub async fn get_routing_events<T>(
    merchant_id: &common_utils::id_type::MerchantId,
    query_param: RoutingEventsRequest,
    pool: &T,
) -> FiltersResult<Vec<RoutingEventsResult>>
where
    T: AnalyticsDataSource + RoutingEventLogAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::RoutingEvents);
    query_builder.add_select_column("*").switch()?;

    query_builder
        .add_filter_clause("merchant_id", merchant_id)
        .switch()?;

    query_builder
        .add_filter_clause("payment_id", &query_param.payment_id)
        .switch()?;

    if let Some(refund_id) = query_param.refund_id {
        query_builder
            .add_filter_clause("refund_id", &refund_id)
            .switch()?;
    }

    if let Some(dispute_id) = query_param.dispute_id {
        query_builder
            .add_filter_clause("dispute_id", &dispute_id)
            .switch()?;
    }

    query_builder
        .execute_query::<RoutingEventsResult, _>(pool)
        .await
        .change_context(FiltersError::QueryBuildingError)?
        .change_context(FiltersError::QueryExecutionFailure)
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct RoutingEventsResult {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_id: String,
    pub routable_connectors: String,
    pub payment_connector: Option<String>,
    pub request_id: Option<String>,
    pub flow: String,
    pub url: Option<String>,
    pub request: String,
    pub response: Option<String>,
    pub error: Option<String>,
    pub status_code: Option<u16>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    pub method: String,
    pub routing_engine: String,
    pub routing_approach: Option<String>,
}


pub struct PlaidBankAccountCredentialsEFT {
    pub account_id: String,
    pub account: String,
    pub institution: String,
    pub branch: String,
}


pub struct ShippingAddress {
    pub salutation: Option<Secret<String>>,
    pub first_name: Option<Secret<String>>,
    pub last_name: Option<Secret<String>>,
    pub address: Option<Secret<String>>,
    pub cell: Option<Secret<String>>,
    pub phone: Option<Secret<String>>,
    pub zip: Option<Secret<String>>,
    pub city: Option<Secret<String>>,
    pub country: api_models::enums::CountryAlpha2,
    pub state: Option<Secret<String>>,
    pub email: Email,
    pub county: Option<Secret<String>>,
    pub address_line2: Option<Secret<String>>,
    pub address_line3: Option<Secret<String>>,
    pub street_number: Option<Secret<String>>,
    pub company_name: Option<Secret<String>>,
    pub care_of: Option<Secret<String>>,
}


impl api::Refund for Payu {}


pub struct SessionRoutingPmTypeInput<'a> {
    state: &'a SessionState,
    key_store: &'a domain::MerchantKeyStore,
    attempt_id: &'a str,
    routing_algorithm: &'a MerchantAccountRoutingAlgorithm,
    backend_input: dsl_inputs::BackendInput,
    allowed_connectors: FxHashMap<String, api::GetToken>,
    profile_id: &'a common_utils::id_type::ProfileId,
}


impl FrmMetricsBucketIdentifier {
    pub fn new(
        frm_status: Option<String>,
        frm_name: Option<String>,
        frm_transaction_type: Option<String>,
        normalized_time_range: TimeRange,
    ) -> Self {
        Self {
            frm_status,
            frm_name,
            frm_transaction_type,
            time_bucket: normalized_time_range,
            start_time: normalized_time_range.start_time,
        }
    }
}


                Box::new(DokuBankData::try_from(item)?),
            )),
            BankTransferData::BniVaBankTransfer {} => Ok(AdyenPaymentMethod::BniVa(Box::new(
                DokuBankData::try_from(item)?,
            ))),
            BankTransferData::BriVaBankTransfer {} => Ok(AdyenPaymentMethod::BriVa(Box::new(
                DokuBankData::try_from(item)?,
            ))),
            BankTransferData::CimbVaBankTransfer {} => Ok(AdyenPaymentMethod::CimbVa(Box::new(
                DokuBankData::try_from(item)?,
            ))),
            BankTransferData::DanamonVaBankTransfer {} => Ok(AdyenPaymentMethod::DanamonVa(
                Box::new(DokuBankData::try_from(item)?),
            )),
            BankTransferData::MandiriVaBankTransfer {} => Ok(AdyenPaymentMethod::MandiriVa(
                Box::new(DokuBankData::try_from(item)?),
            )),
            BankTransferData::Pix { .. } => Ok(AdyenPaymentMethod::Pix),
            BankTransferData::AchBankTransfer { .. }
            | BankTransferData::SepaBankTransfer { .. }
            | BankTransferData::BacsBankTransfer { .. }
            | BankTransferData::MultibancoBankTransfer { .. }
            | BankTransferData::LocalBankTransfer { .. }
            | BankTransferData::InstantBankTransfer {}
            | BankTransferData::InstantBankTransferFinland {}
            | BankTransferData::InstantBankTransferPoland {}
            | BankTransferData::IndonesianBankTransfer { .. }
            | BankTransferData::Pse {} => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

impl TryFrom<&PaymentsAuthorizeRouterData> for DokuBankData {
    type Error = Error;
    fn try_from(item: &PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
        Ok(Self {
            first_name: item.get_billing_first_name()?,
            last_name: item.get_optional_billing_last_name(),
            shopper_email: item.get_billing_email()?,
        })
    }
}

impl TryFrom<&CardRedirectData> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(card_redirect_data: &CardRedirectData) -> Result<Self, Self::Error> {
        match card_redirect_data {
            CardRedirectData::Knet {} => Ok(AdyenPaymentMethod::Knet),
            CardRedirectData::Benefit {} => Ok(AdyenPaymentMethod::Benefit),
            CardRedirectData::MomoAtm {} => Ok(AdyenPaymentMethod::MomoAtm),
            CardRedirectData::CardRedirect {} => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

fn get_str(key: &str, riskdata: &serde_json::Value) -> Option<String> {
    riskdata
        .get(key)
        .and_then(|v| v.as_str())
        .map(|s| s.to_string())
}

fn get_bool(key: &str, riskdata: &serde_json::Value) -> Option<bool> {
    riskdata.get(key).and_then(|v| v.as_bool())
}

pub fn get_risk_data(metadata: serde_json::Value) -> Option<RiskData> {
    let item_i_d = get_str("riskdata.basket.item1.itemID", &metadata);
    let product_title = get_str("riskdata.basket.item1.productTitle", &metadata);
    let amount_per_item = get_str("riskdata.basket.item1.amountPerItem", &metadata);
    let currency = get_str("riskdata.basket.item1.currency", &metadata);
    let upc = get_str("riskdata.basket.item1.upc", &metadata);
    let brand = get_str("riskdata.basket.item1.brand", &metadata);
    let manufacturer = get_str("riskdata.basket.item1.manufacturer", &metadata);
    let category = get_str("riskdata.basket.item1.category", &metadata);
    let quantity = get_str("riskdata.basket.item1.quantity", &metadata);
    let color = get_str("riskdata.basket.item1.color", &metadata);
    let size = get_str("riskdata.basket.item1.size", &metadata);

    let device_country = get_str("riskdata.deviceCountry", &metadata);
    let house_numberor_name = get_str("riskdata.houseNumberorName", &metadata);
    let account_creation_date = get_str("riskdata.accountCreationDate", &metadata);
    let affiliate_channel = get_str("riskdata.affiliateChannel", &metadata);
    let avg_order_value = get_str("riskdata.avgOrderValue", &metadata);
    let delivery_method = get_str("riskdata.deliveryMethod", &metadata);
    let email_name = get_str("riskdata.emailName", &metadata);
    let email_domain = get_str("riskdata.emailDomain", &metadata);
    let last_order_date = get_str("riskdata.lastOrderDate", &metadata);
    let merchant_reference = get_str("riskdata.merchantReference", &metadata);
    let payment_method = get_str("riskdata.paymentMethod", &metadata);
    let promotion_name = get_str("riskdata.promotionName", &metadata);
    let secondary_phone_number = get_str("riskdata.secondaryPhoneNumber", &metadata);
    let timefrom_loginto_order = get_str("riskdata.timefromLogintoOrder", &metadata);
    let total_session_time = get_str("riskdata.totalSessionTime", &metadata);
    let total_authorized_amount_in_last30_days =
        get_str("riskdata.totalAuthorizedAmountInLast30Days", &metadata);
    let total_order_quantity = get_str("riskdata.totalOrderQuantity", &metadata);
    let total_lifetime_value = get_str("riskdata.totalLifetimeValue", &metadata);
    let visits_month = get_str("riskdata.visitsMonth", &metadata);
    let visits_week = get_str("riskdata.visitsWeek", &metadata);
    let visits_year = get_str("riskdata.visitsYear", &metadata);
    let ship_to_name = get_str("riskdata.shipToName", &metadata);
    let first8charactersof_address_line1_zip =
        get_str("riskdata.first8charactersofAddressLine1Zip", &metadata);
    let affiliate_order = get_bool("riskdata.affiliateOrder", &metadata);

    Some(RiskData {
        item_i_d,
        product_title,
        amount_per_item,
        currency,
        upc,
        brand,
        manufacturer,
        category,
        quantity,
        color,
        size,
        device_country,
        house_numberor_name,
        account_creation_date,
        affiliate_channel,
        avg_order_value,
        delivery_method,
        email_name,
        email_domain,
        last_order_date,
        merchant_reference,
        payment_method,
        promotion_name,
        secondary_phone_number,
        timefrom_loginto_order,
        total_session_time,
        total_authorized_amount_in_last30_days,
        total_order_quantity,
        total_lifetime_value,
        visits_month,
        visits_week,
        visits_year,
        ship_to_name,
        first8charactersof_address_line1_zip,
        affiliate_order,
    })
}

fn get_device_fingerprint(metadata: serde_json::Value) -> Option<Secret<String>> {
    metadata
        .get("device_fingerprint")
        .and_then(|value| value.as_str())
        .map(|fingerprint| Secret::new(fingerprint.to_string()))
}

impl
    TryFrom<(
        &AdyenRouterData<&PaymentsAuthorizeRouterData>,
        payments::MandateReferenceId,
    )> for AdyenPaymentRequest<'_>
{
    type Error = Error;
    fn try_from(
        value: (
            &AdyenRouterData<&PaymentsAuthorizeRouterData>,
            payments::MandateReferenceId,
        ),
    ) -> Result<Self, Self::Error> {
        let (item, mandate_ref_id) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let (recurring_processing_model, store_payment_method, shopper_reference) =
            get_recurring_processing_model(item.router_data)?;
        let browser_info = None;
        let additional_data = get_additional_data(item.router_data);
        let return_url = item.router_data.request.get_router_return_url()?;
        let payment_method_type = item.router_data.request.payment_method_type;
        let testing_data = item
            .router_data
            .request
            .get_connector_testing_data()
            .map(AdyenTestingData::try_from)
            .transpose()?;
        let test_holder_name = testing_data.and_then(|test_data| test_data.holder_name);
        let payment_method = match mandate_ref_id {
            payments::MandateReferenceId::ConnectorMandateId(connector_mandate_ids) => {
                let adyen_mandate = AdyenMandate {
                    payment_type: match payment_method_type {
                        Some(pm_type) => PaymentType::try_from(&pm_type)?,
                        None => PaymentType::Scheme,
                    },
                    stored_payment_method_id: Secret::new(
                        connector_mandate_ids
                            .get_connector_mandate_id()
                            .ok_or_else(missing_field_err("mandate_id"))?,
                    ),
                    holder_name: test_holder_name,
                };
                Ok::<PaymentMethod<'_>, Self::Error>(PaymentMethod::AdyenMandatePaymentMethod(
                    Box::new(adyen_mandate),
                ))
            }
            payments::MandateReferenceId::NetworkMandateId(network_mandate_id) => {
                match item.router_data.request.payment_method_data {
                    PaymentMethodData::CardDetailsForNetworkTransactionId(
                        ref card_details_for_network_transaction_id,
                    ) => {
                        let brand = match card_details_for_network_transaction_id
                            .card_network
                            .clone()
                            .and_then(get_adyen_card_network)
                        {
                            Some(card_network) => card_network,
                            None => CardBrand::try_from(
                                &card_details_for_network_transaction_id.get_card_issuer()?,
                            )?,
                        };

                        let card_holder_name = item.router_data.get_optional_billing_full_name();
                        let adyen_card = AdyenCard {
                            number: card_details_for_network_transaction_id.card_number.clone(),
                            expiry_month: card_details_for_network_transaction_id
                                .card_exp_month
                                .clone(),
                            expiry_year: card_details_for_network_transaction_id
                                .get_expiry_year_4_digit()
                                .clone(),
                            cvc: None,
                            holder_name: test_holder_name.or(card_holder_name),
                            brand: Some(brand),
                            network_payment_reference: Some(Secret::new(network_mandate_id)),
                        };
                        Ok(PaymentMethod::AdyenPaymentMethod(Box::new(
                            AdyenPaymentMethod::AdyenCard(Box::new(adyen_card)),
                        )))
                    }
                    PaymentMethodData::CardRedirect(_)
                    | PaymentMethodData::Wallet(_)
                    | PaymentMethodData::PayLater(_)
                    | PaymentMethodData::BankRedirect(_)
                    | PaymentMethodData::BankDebit(_)
                    | PaymentMethodData::BankTransfer(_)
                    | PaymentMethodData::Crypto(_)
                    | PaymentMethodData::MandatePayment
                    | PaymentMethodData::Reward
                    | PaymentMethodData::RealTimePayment(_)
                    | PaymentMethodData::MobilePayment(_)
                    | PaymentMethodData::Upi(_)
                    | PaymentMethodData::Voucher(_)
                    | PaymentMethodData::GiftCard(_)
                    | PaymentMethodData::OpenBanking(_)
                    | PaymentMethodData::CardToken(_)
                    | PaymentMethodData::NetworkToken(_)
                    | PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotSupported {
                        message: "Network tokenization for payment method".to_string(),
                        connector: "Adyen",
                    })?,
                }
            }
            payments::MandateReferenceId::NetworkTokenWithNTI(network_mandate_id) => {
                match item.router_data.request.payment_method_data {
                    PaymentMethodData::NetworkToken(ref token_data) => {
                        let card_issuer = token_data.get_card_issuer()?;
                        let brand = CardBrand::try_from(&card_issuer)?;
                        let card_holder_name = item.router_data.get_optional_billing_full_name();
                        let adyen_network_token = AdyenNetworkTokenData {
                            number: token_data.get_network_token(),
                            expiry_month: token_data.get_network_token_expiry_month(),
                            expiry_year: token_data.get_expiry_year_4_digit(),
                            holder_name: test_holder_name.or(card_holder_name),
                            brand: Some(brand), // FIXME: Remove hardcoding
                            network_payment_reference: Some(Secret::new(
                                network_mandate_id.network_transaction_id,
                            )),
                        };
                        Ok(PaymentMethod::AdyenPaymentMethod(Box::new(
                            AdyenPaymentMethod::NetworkToken(Box::new(adyen_network_token)),
                        )))
                    }

                    PaymentMethodData::Card(_)
                    | PaymentMethodData::CardRedirect(_)
                    | PaymentMethodData::Wallet(_)
                    | PaymentMethodData::PayLater(_)
                    | PaymentMethodData::BankRedirect(_)
                    | PaymentMethodData::BankDebit(_)
                    | PaymentMethodData::BankTransfer(_)
                    | PaymentMethodData::Crypto(_)
                    | PaymentMethodData::MandatePayment
                    | PaymentMethodData::Reward
                    | PaymentMethodData::RealTimePayment(_)
                    | PaymentMethodData::Upi(_)
                    | PaymentMethodData::Voucher(_)
                    | PaymentMethodData::GiftCard(_)
                    | PaymentMethodData::OpenBanking(_)
                    | PaymentMethodData::CardToken(_)
                    | PaymentMethodData::MobilePayment(_)
                    | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
                        Err(errors::ConnectorError::NotSupported {
                            message: "Network tokenization for payment method".to_string(),
                            connector: "Adyen",
                        })?
                    }
                }
            } //
        }?;

        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        Ok(AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.clone(),
            return_url,
            shopper_interaction,
            recurring_processing_model,
            browser_info,
            additional_data,
            mpi_data: None,
            telephone_number,
            shopper_name: None,
            shopper_email: None,
            shopper_locale: item.router_data.request.locale.clone(),
            social_security_number: None,
            billing_address,
            delivery_address,
            country_code: None,
            line_items: None,
            shopper_reference,
            store_payment_method,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        })
    }
}
impl TryFrom<(&AdyenRouterData<&PaymentsAuthorizeRouterData>, &Card)> for AdyenPaymentRequest<'_> {
    type Error = Error;
    fn try_from(
        value: (&AdyenRouterData<&PaymentsAuthorizeRouterData>, &Card),
    ) -> Result<Self, Self::Error> {
        let (item, card_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let shopper_reference = build_shopper_reference(item.router_data);
        let (recurring_processing_model, store_payment_method, _) =
            get_recurring_processing_model(item.router_data)?;
        let browser_info = get_browser_info(item.router_data)?;
        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let country_code = get_country_code(item.router_data.get_optional_billing());
        let additional_data = get_additional_data(item.router_data);
        let return_url = item.router_data.request.get_router_return_url()?;
        let testing_data = item
            .router_data
            .request
            .get_connector_testing_data()
            .map(AdyenTestingData::try_from)
            .transpose()?;
        let test_holder_name = testing_data.and_then(|test_data| test_data.holder_name);
        let card_holder_name =
            test_holder_name.or(item.router_data.get_optional_billing_full_name());
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((card_data, card_holder_name))?,
        ));

        let shopper_email = item.router_data.get_optional_billing_email();
        let shopper_name = get_shopper_name(item.router_data.get_optional_billing());
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        Ok(AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.clone(),
            return_url,
            shopper_interaction,
            recurring_processing_model,
            browser_info,
            additional_data,
            mpi_data: None,
            telephone_number,
            shopper_name,
            shopper_email,
            shopper_locale: item.router_data.request.locale.clone(),
            social_security_number: None,
            billing_address,
            delivery_address,
            country_code,
            line_items: None,
            shopper_reference,
            store_payment_method,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        })
    }
}

impl
    TryFrom<(
        &AdyenRouterData<&PaymentsAuthorizeRouterData>,
        &BankDebitData,
    )> for AdyenPaymentRequest<'_>
{
    type Error = Error;

    fn try_from(
        value: (
            &AdyenRouterData<&PaymentsAuthorizeRouterData>,
            &BankDebitData,
        ),
    ) -> Result<Self, Self::Error> {
        let (item, bank_debit_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let (recurring_processing_model, store_payment_method, shopper_reference) =
            get_recurring_processing_model(item.router_data)?;
        let browser_info = get_browser_info(item.router_data)?;
        let additional_data = get_additional_data(item.router_data);
        let return_url = item.router_data.request.get_router_return_url()?;
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((bank_debit_data, item.router_data))?,
        ));

        let country_code = get_country_code(item.router_data.get_optional_billing());
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let mut billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        if let BankDebitData::AchBankDebit { .. } = bank_debit_data {
            if let Some(addr) = billing_address.as_mut() {
                addr.state_or_province = Some(item.router_data.get_billing_state_code()?);
            }
        }

        let request = AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.clone(),
            return_url,
            browser_info,
            shopper_interaction,
            recurring_processing_model,
            additional_data,
            mpi_data: None,
            shopper_name: None,
            shopper_locale: item.router_data.request.locale.clone(),
            shopper_email: item.router_data.get_optional_billing_email(),
            social_security_number: None,
            telephone_number,
            billing_address,
            delivery_address,
            country_code,
            line_items: None,
            shopper_reference,
            store_payment_method,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        };
        Ok(request)
    }
}

impl TryFrom<(&AdyenRouterData<&PaymentsAuthorizeRouterData>, &VoucherData)>
    for AdyenPaymentRequest<'_>
{
    type Error = Error;

    fn try_from(
        value: (&AdyenRouterData<&PaymentsAuthorizeRouterData>, &VoucherData),
    ) -> Result<Self, Self::Error> {
        let (item, voucher_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let recurring_processing_model = get_recurring_processing_model(item.router_data)?.0;
        let browser_info = get_browser_info(item.router_data)?;
        let additional_data = get_additional_data(item.router_data);
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((voucher_data, item.router_data))?,
        ));
        let return_url = item.router_data.request.get_router_return_url()?;
        let social_security_number = get_social_security_number(voucher_data);
        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let shopper_name = get_shopper_name(item.router_data.get_optional_billing());
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        let request = AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.to_string(),
            return_url,
            browser_info,
            shopper_interaction,
            recurring_processing_model,
            additional_data,
            shopper_name,
            shopper_locale: item.router_data.request.locale.clone(),
            shopper_email: item.router_data.get_optional_billing_email(),
            social_security_number,
            mpi_data: None,
            telephone_number,
            billing_address,
            delivery_address,
            country_code: None,
            line_items: None,
            shopper_reference: None,
            store_payment_method: None,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        };
        Ok(request)
    }
}

impl
    TryFrom<(
        &AdyenRouterData<&PaymentsAuthorizeRouterData>,
        &BankTransferData,
    )> for AdyenPaymentRequest<'_>
{
    type Error = Error;

    fn try_from(
        value: (
            &AdyenRouterData<&PaymentsAuthorizeRouterData>,
            &BankTransferData,
        ),
    ) -> Result<Self, Self::Error> {
        let (item, bank_transfer_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((bank_transfer_data, item.router_data))?,
        ));

        let return_url = item.router_data.request.get_router_return_url()?;
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);
        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();
        let (session_validity, social_security_number) = match bank_transfer_data {
            BankTransferData::Pix {
                cpf,
                cnpj,
                expiry_date,
                ..
            } => {
                // Validate expiry_date doesn't exceed 5 days from now
                if let Some(expiry) = expiry_date {
                    let now = OffsetDateTime::now_utc();
                    let max_expiry = now + Duration::days(5);
                    let max_expiry_primitive =
                        PrimitiveDateTime::new(max_expiry.date(), max_expiry.time());

                    if *expiry > max_expiry_primitive {
                        return Err(report!(errors::ConnectorError::InvalidDataFormat {
                            field_name: "expiry_date cannot be more than 5 days from now",
                        }));
                    }
                }

                (*expiry_date, cpf.as_ref().or(cnpj.as_ref()).cloned())
            }
            BankTransferData::LocalBankTransfer { .. } => (None, None),
            BankTransferData::AchBankTransfer {}
            | BankTransferData::SepaBankTransfer {}
            | BankTransferData::BacsBankTransfer {}
            | BankTransferData::MultibancoBankTransfer {}
            | BankTransferData::PermataBankTransfer {}
            | BankTransferData::BcaBankTransfer {}
            | BankTransferData::BniVaBankTransfer {}
            | BankTransferData::BriVaBankTransfer {}
            | BankTransferData::CimbVaBankTransfer {}
            | BankTransferData::DanamonVaBankTransfer {}
            | BankTransferData::MandiriVaBankTransfer {}
            | BankTransferData::Pse {}
            | BankTransferData::InstantBankTransfer {}
            | BankTransferData::InstantBankTransferFinland {}
            | BankTransferData::InstantBankTransferPoland {}
            | BankTransferData::IndonesianBankTransfer { .. } => (None, None),
        };

        let request = AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.to_string(),
            return_url,
            browser_info: None,
            shopper_interaction,
            recurring_processing_model: None,
            additional_data: None,
            mpi_data: None,
            shopper_name: None,
            shopper_locale: item.router_data.request.locale.clone(),
            shopper_email: item.router_data.get_optional_billing_email(),
            social_security_number,
            telephone_number,
            billing_address,
            delivery_address,
            country_code: None,
            line_items: None,
            shopper_reference: None,
            store_payment_method: None,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity,
            metadata: item.router_data.request.metadata.clone(),
        };
        Ok(request)
    }
}

impl
    TryFrom<(
        &AdyenRouterData<&PaymentsAuthorizeRouterData>,
        &GiftCardData,
    )> for AdyenPaymentRequest<'_>
{
    type Error = Error;

    fn try_from(
        value: (
            &AdyenRouterData<&PaymentsAuthorizeRouterData>,
            &GiftCardData,
        ),
    ) -> Result<Self, Self::Error> {
        let (item, gift_card_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let return_url = item.router_data.request.get_router_return_url()?;
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from(gift_card_data)?,
        ));
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };

        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        let request = AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.to_string(),
            return_url,
            browser_info: None,
            shopper_interaction,
            recurring_processing_model: None,
            additional_data: None,
            mpi_data: None,
            shopper_name: None,
            shopper_locale: item.router_data.request.locale.clone(),
            shopper_email: item.router_data.get_optional_billing_email(),
            telephone_number,
            billing_address,
            delivery_address,
            country_code: None,
            line_items: None,
            shopper_reference: None,
            store_payment_method: None,
            channel: None,
            social_security_number: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        };
        Ok(request)
    }
}

impl
    TryFrom<(
        &AdyenRouterData<&PaymentsAuthorizeRouterData>,
        &BankRedirectData,
    )> for AdyenPaymentRequest<'_>
{
    type Error = Error;
    fn try_from(
        value: (
            &AdyenRouterData<&PaymentsAuthorizeRouterData>,
            &BankRedirectData,
        ),
    ) -> Result<Self, Self::Error> {
        let (item, bank_redirect_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let (recurring_processing_model, store_payment_method, shopper_reference) =
            get_recurring_processing_model(item.router_data)?;
        let browser_info = get_browser_info(item.router_data)?;
        let additional_data = get_additional_data(item.router_data);
        let return_url = item.router_data.request.get_router_return_url()?;
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((bank_redirect_data, item.router_data))?,
        ));
        let (shopper_locale, country) = get_redirect_extra_details(item.router_data)?;
        let line_items = Some(get_line_items(item));
        let billing_address =
            get_address_info(item.router_data.get_optional_billing()).and_then(Result::ok);
        let (store, splits) = match item.router_data.request.split_payments.as_ref() {
            Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
                adyen_split_payment,
            )) => get_adyen_split_request(adyen_split_payment, item.router_data.request.currency),
            _ => (None, None),
        };
        let device_fingerprint = item
            .router_data
            .request
            .metadata
            .clone()
            .and_then(get_device_fingerprint);

        let delivery_address =
            get_address_info(item.router_data.get_optional_shipping()).and_then(Result::ok);
        let telephone_number = item.router_data.get_optional_billing_phone_number();

        Ok(AdyenPaymentRequest {
            amount,
            merchant_account: auth_type.merchant_account,
            payment_method,
            reference: item.router_data.connector_request_reference_id.clone(),
            return_url,
            shopper_interaction,
            recurring_processing_model,
            browser_info,
            additional_data,
            mpi_data: None,
            telephone_number,
            shopper_name: None,
            shopper_email: item.router_data.get_optional_billing_email(),
            shopper_locale,
            social_security_number: None,
            billing_address,
            delivery_address,
            country_code: country,
            line_items,
            shopper_reference,
            store_payment_method,
            channel: None,
            shopper_statement: item.router_data.request.statement_descriptor.clone(),
            shopper_ip: item.router_data.request.get_ip_address_as_optional(),
            merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
            store,
            splits,
            device_fingerprint,
            session_validity: None,
            metadata: item.router_data.request.metadata.clone(),
        })
    }
}

fn get_redirect_extra_details(
    item: &PaymentsAuthorizeRouterData,
) -> CustomResult<(Option<String>, Option<storage_enums::CountryAlpha2>), errors::ConnectorError> {
    match item.request.payment_method_data {
        PaymentMethodData::BankRedirect(
            BankRedirectData::Trustly { .. } | BankRedirectData::OpenBankingUk { .. },
        ) => {
            let country = item.get_optional_billing_country();
            Ok((item.request.locale.clone(), country))
        }
        _ => Ok((None, None)),
    }
}

fn get_shopper_email(
    item: &PaymentsAuthorizeRouterData,
    is_mandate_payment: bool,
) -> CustomResult<Option<Email>, errors::ConnectorError> {
    if is_mandate_payment {
        let payment_method_type = item
            .request
            .payment_method_type
            .as_ref()
            .ok_or(errors::ConnectorError::MissingPaymentMethodType)?;
        match payment_method_type {
            storage_enums::PaymentMethodType::Paypal => Ok(Some(item.get_billing_email()?)),
            _ => Ok(item.get_optional_billing_email()),
        }
    } else {
        Ok(item.get_optional_billing_email())
    }
}

impl TryFrom<(&AdyenRouterData<&PaymentsAuthorizeRouterData>, &WalletData)>
    for AdyenPaymentRequest<'_>
{
    type Error = Error;
    fn try_from(
        value: (&AdyenRouterData<&PaymentsAuthorizeRouterData>, &WalletData),
    ) -> Result<Self, Self::Error> {
        let (item, wallet_data) = value;
        let amount = get_amount_data(item);
        let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
        let browser_info = get_browser_info(item.router_data)?;
        let additional_data = get_additional_data(item.router_data);
        let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
            AdyenPaymentMethod::try_from((wallet_data, item.router_data))?,
        ));
        let shopper_interaction = AdyenShopperInteraction::from(item.router_data);
        let channel = get_channel_type(item.router_data.request.payment_method_type);
        let (recurring_processing_model, store_payment_method, shopper_reference) =
            get_recurring_processing_model(item.router_data)?;
        let return_url = item.router_data.request.get_router_return_url()?;
        let shopper_email = get_shopper_email(item.router_data, store_payment_method.is_some())?;
        let billing_address =


pub struct ProfileAcquirerCreate {
    /// The merchant id assigned by the acquirer
    #[schema(value_type= String,example = "M123456789")]
    pub acquirer_assigned_merchant_id: String,
    /// merchant name
    #[schema(value_type= String,example = "NewAge Retailer")]
    pub merchant_name: String,
    /// Network provider
    #[schema(value_type= String,example = "VISA")]
    pub network: common_enums::enums::CardNetwork,
    /// Acquirer bin
    #[schema(value_type= String,example = "456789")]
    pub acquirer_bin: String,
    /// Acquirer ica provided by acquirer
    #[schema(value_type= Option<String>,example = "401288")]
    pub acquirer_ica: Option<String>,
    /// Fraud rate for the particular acquirer configuration
    #[schema(value_type= f64,example = 0.01)]
    pub acquirer_fraud_rate: f64,
    /// Parent profile id to link the acquirer account with
    #[schema(value_type= String,example = "pro_ky0yNyOXXlA5hF8JzE5q")]
    pub profile_id: common_utils::id_type::ProfileId,
}


impl api::Payment for Trustpayments {}


OpenAPI Block Path: components.schemas.NextActionType
{
  "type": "string",
  "enum": [
    "redirect_to_url",
    "display_qr_code",
    "invoke_sdk_client",
    "trigger_api",
    "display_bank_transfer_information",
    "display_wait_screen",
    "collect_otp",
    "redirect_inside_popup"
  ]
}


pub async fn payment_connector_list_profile() {}


impl PaymentVoid for Signifyd {}


pub trait ActivePaymentsMetricAnalytics: LoadRow<ActivePaymentsMetricRow> {}


pub struct OpensearchResultsTotal {
    pub value: u64,
}


pub struct DummyConnectorPaymentData {
    pub attempt_id: String,
    pub payment_id: common_utils::id_type::PaymentId,
    pub status: DummyConnectorStatus,
    pub amount: i64,
    pub eligible_amount: i64,
    pub currency: Currency,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created: PrimitiveDateTime,
    pub payment_method_type: DummyConnectorPaymentMethodType,
    pub connector: DummyConnectors,
    pub next_action: Option<DummyConnectorNextAction>,
    pub return_url: Option<String>,
}


impl fmt::Display for BokuChargeType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Hosted => write!(f, "hosted"),
        }
    }
}

impl fmt::Display for for BokuChargeType


/// Three letter (lowercase) prefix corresponding to the current environment.
/// Either `dev`, `snd` or `prd`.
pub fn prefix_for_env() -> &'static str {
    match which() {
        Env::Development => "dev",
        Env::Sandbox => "snd",
        Env::Production => "prd",
    }
}


impl Routing {
    pub fn server(state: AppState) -> Scope {
        #[allow(unused_mut)]
        let mut route = web::scope("/routing")
            .app_data(web::Data::new(state.clone()))
            .service(
                web::resource("/active").route(web::get().to(|state, req, query_params| {
                    routing::routing_retrieve_linked_config(state, req, query_params, None)
                })),
            )
            .service(
                web::resource("")
                    .route(
                        web::get().to(|state, req, path: web::Query<RoutingRetrieveQuery>| {
                            routing::list_routing_configs(state, req, path, None)
                        }),
                    )
                    .route(web::post().to(|state, req, payload| {
                        routing::routing_create_config(state, req, payload, None)
                    })),
            )
            .service(web::resource("/list/profile").route(web::get().to(
                |state, req, query: web::Query<RoutingRetrieveQuery>| {
                    routing::list_routing_configs_for_profile(state, req, query, None)
                },
            )))
            .service(
                web::resource("/default").route(web::post().to(|state, req, payload| {
                    routing::routing_update_default_config(
                        state,
                        req,
                        payload,
                        &TransactionType::Payment,
                    )
                })),
            )
            .service(web::resource("/rule/migrate").route(web::post().to(
                |state, req, query: web::Query<RuleMigrationQuery>| {
                    routing::migrate_routing_rules_for_profile(state, req, query)
                },
            )))
            .service(
                web::resource("/deactivate").route(web::post().to(|state, req, payload| {
                    routing::routing_unlink_config(state, req, payload, None)
                })),
            )
            .service(
                web::resource("/decision")
                    .route(web::put().to(routing::upsert_decision_manager_config))
                    .route(web::get().to(routing::retrieve_decision_manager_config))
                    .route(web::delete().to(routing::delete_decision_manager_config)),
            )
            .service(
                web::resource("/decision/surcharge")
                    .route(web::put().to(routing::upsert_surcharge_decision_manager_config))
                    .route(web::get().to(routing::retrieve_surcharge_decision_manager_config))
                    .route(web::delete().to(routing::delete_surcharge_decision_manager_config)),
            )
            .service(
                web::resource("/default/profile/{profile_id}").route(web::post().to(
                    |state, req, path, payload| {
                        routing::routing_update_default_config_for_profile(
                            state,
                            req,
                            path,
                            payload,
                            &TransactionType::Payment,
                        )
                    },
                )),
            )
            .service(
                web::resource("/default/profile").route(web::get().to(|state, req| {
                    routing::routing_retrieve_default_config(state, req, &TransactionType::Payment)
                })),
            );

        #[cfg(feature = "dynamic_routing")]
        {
            route = route
                .service(
                    web::resource("/evaluate")
                        .route(web::post().to(routing::call_decide_gateway_open_router)),
                )
                .service(
                    web::resource("/feedback")
                        .route(web::post().to(routing::call_update_gateway_score_open_router)),
                )
        }

        #[cfg(feature = "payouts")]
        {
            route = route
                .service(
                    web::resource("/payouts")
                        .route(web::get().to(
                            |state, req, path: web::Query<RoutingRetrieveQuery>| {
                                routing::list_routing_configs(
                                    state,
                                    req,
                                    path,
                                    Some(TransactionType::Payout),
                                )
                            },
                        ))
                        .route(web::post().to(|state, req, payload| {
                            routing::routing_create_config(
                                state,
                                req,
                                payload,
                                Some(TransactionType::Payout),
                            )
                        })),
                )
                .service(web::resource("/payouts/list/profile").route(web::get().to(
                    |state, req, query: web::Query<RoutingRetrieveQuery>| {
                        routing::list_routing_configs_for_profile(
                            state,
                            req,
                            query,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(web::resource("/payouts/active").route(web::get().to(
                    |state, req, query_params| {
                        routing::routing_retrieve_linked_config(
                            state,
                            req,
                            query_params,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(
                    web::resource("/payouts/default")
                        .route(web::get().to(|state, req| {
                            routing::routing_retrieve_default_config(
                                state,
                                req,
                                &TransactionType::Payout,
                            )
                        }))
                        .route(web::post().to(|state, req, payload| {
                            routing::routing_update_default_config(
                                state,
                                req,
                                payload,
                                &TransactionType::Payout,
                            )
                        })),
                )
                .service(
                    web::resource("/payouts/{algorithm_id}/activate").route(web::post().to(
                        |state, req, path, payload| {
                            routing::routing_link_config(
                                state,
                                req,
                                path,
                                payload,
                                Some(TransactionType::Payout),
                            )
                        },
                    )),
                )
                .service(web::resource("/payouts/deactivate").route(web::post().to(
                    |state, req, payload| {
                        routing::routing_unlink_config(
                            state,
                            req,
                            payload,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(
                    web::resource("/payouts/default/profile/{profile_id}").route(web::post().to(
                        |state, req, path, payload| {
                            routing::routing_update_default_config_for_profile(
                                state,
                                req,
                                path,
                                payload,
                                &TransactionType::Payout,
                            )
                        },
                    )),
                )
                .service(
                    web::resource("/payouts/default/profile").route(web::get().to(|state, req| {
                        routing::routing_retrieve_default_config_for_profiles(
                            state,
                            req,
                            &TransactionType::Payout,
                        )
                    })),
                );
        }

        route = route
            .service(
                web::resource("/{algorithm_id}")
                    .route(web::get().to(routing::routing_retrieve_config)),
            )
            .service(
                web::resource("/{algorithm_id}/activate").route(web::post().to(
                    |state, req, payload, path| {
                        routing::routing_link_config(state, req, path, payload, None)
                    },
                )),
            )
            .service(
                web::resource("/rule/evaluate")
                    .route(web::post().to(routing::evaluate_routing_rule)),
            );
        route
    }
}


pub struct RefundDistributionBody {
    pub distribution_for: RefundDistributions,
    pub distribution_cardinality: QueryLimit,
}


impl EmailData for BizEmailProd {
    async fn get_email_data(&self, _base_url: &str) -> CustomResult<EmailContents, EmailError> {
        let body = html::get_html_body(EmailBody::BizEmailProd {
            user_name: self.user_name.clone().expose(),
            poc_email: self.poc_email.clone().expose(),
            legal_business_name: self.legal_business_name.clone(),
            business_location: self.business_location.clone(),
            business_website: self.business_website.clone(),
            product_type: self.product_type,
        });

        Ok(EmailContents {
            subject: "New Prod Intent".to_string(),
            body: external_services::email::IntermediateString::new(body),
            recipient: self.recipient_email.clone().into_inner(),
        })
    }
}


pub async fn update_trackers<F: Clone, Req>(
    state: &SessionState,
    router_data: RouterData<F, Req, AuthenticationResponseData>,
    authentication: storage::Authentication,
    acquirer_details: Option<super::types::AcquirerDetails>,
    merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
) -> RouterResult<storage::Authentication> {
    let authentication_update = match router_data.response {
        Ok(response) => match response {
            AuthenticationResponseData::PreAuthNResponse {
                threeds_server_transaction_id,
                maximum_supported_3ds_version,
                connector_authentication_id,
                three_ds_method_data,
                three_ds_method_url,
                message_version,
                connector_metadata,
                directory_server_id,
            } => storage::AuthenticationUpdate::PreAuthenticationUpdate {
                threeds_server_transaction_id,
                maximum_supported_3ds_version,
                connector_authentication_id,
                three_ds_method_data,
                three_ds_method_url,
                message_version,
                connector_metadata,
                authentication_status: common_enums::AuthenticationStatus::Pending,
                acquirer_bin: acquirer_details
                    .as_ref()
                    .map(|acquirer_details| acquirer_details.acquirer_bin.clone()),
                acquirer_merchant_id: acquirer_details
                    .as_ref()
                    .map(|acquirer_details| acquirer_details.acquirer_merchant_id.clone()),
                acquirer_country_code: acquirer_details
                    .and_then(|acquirer_details| acquirer_details.acquirer_country_code),
                directory_server_id,
                billing_address: None,
                shipping_address: None,
                browser_info: Box::new(None),
                email: None,
            },
            AuthenticationResponseData::AuthNResponse {
                authn_flow_type,
                authentication_value,
                trans_status,
                connector_metadata,
                ds_trans_id,
                eci,
                challenge_code,
                challenge_cancel,
                challenge_code_reason,
                message_extension,
            } => {
                authentication_value
                    .async_map(|auth_val| {
                        crate::core::payment_methods::vault::create_tokenize(
                            state,
                            auth_val.expose(),
                            None,
                            authentication
                                .authentication_id
                                .get_string_repr()
                                .to_string(),
                            merchant_key_store.key.get_inner(),
                        )
                    })
                    .await
                    .transpose()?;

                let authentication_status =
                    common_enums::AuthenticationStatus::foreign_from(trans_status.clone());

                storage::AuthenticationUpdate::AuthenticationUpdate {
                    trans_status,
                    acs_url: authn_flow_type.get_acs_url(),
                    challenge_request: authn_flow_type.get_challenge_request(),
                    acs_reference_number: authn_flow_type.get_acs_reference_number(),
                    acs_trans_id: authn_flow_type.get_acs_trans_id(),
                    acs_signed_content: authn_flow_type.get_acs_signed_content(),
                    authentication_type: authn_flow_type.get_decoupled_authentication_type(),
                    authentication_status,
                    connector_metadata,
                    ds_trans_id,
                    eci,
                    challenge_code,
                    challenge_cancel,
                    challenge_code_reason,
                    message_extension,
                }
            }
            AuthenticationResponseData::PostAuthNResponse {
                trans_status,
                authentication_value,
                eci,
                challenge_cancel,
                challenge_code_reason,
            } => {
                authentication_value
                    .async_map(|auth_val| {
                        crate::core::payment_methods::vault::create_tokenize(
                            state,
                            auth_val.expose(),
                            None,
                            authentication
                                .authentication_id
                                .get_string_repr()
                                .to_string(),
                            merchant_key_store.key.get_inner(),
                        )
                    })
                    .await
                    .transpose()?;
                storage::AuthenticationUpdate::PostAuthenticationUpdate {
                    authentication_status: common_enums::AuthenticationStatus::foreign_from(
                        trans_status.clone(),
                    ),
                    trans_status,
                    eci,
                    challenge_cancel,
                    challenge_code_reason,
                }
            }
            AuthenticationResponseData::PreAuthVersionCallResponse {
                maximum_supported_3ds_version,
            } => storage::AuthenticationUpdate::PreAuthenticationVersionCallUpdate {
                message_version: maximum_supported_3ds_version.clone(),
                maximum_supported_3ds_version,
            },
            AuthenticationResponseData::PreAuthThreeDsMethodCallResponse {
                threeds_server_transaction_id,
                three_ds_method_data,
                three_ds_method_url,
                connector_metadata,
            } => storage::AuthenticationUpdate::PreAuthenticationThreeDsMethodCall {
                threeds_server_transaction_id,
                three_ds_method_data,
                three_ds_method_url,
                connector_metadata,
                acquirer_bin: acquirer_details
                    .as_ref()
                    .map(|acquirer_details| acquirer_details.acquirer_bin.clone()),
                acquirer_merchant_id: acquirer_details
                    .map(|acquirer_details| acquirer_details.acquirer_merchant_id),
            },
        },
        Err(error) => storage::AuthenticationUpdate::ErrorUpdate {
            connector_authentication_id: error.connector_transaction_id,
            authentication_status: common_enums::AuthenticationStatus::Failed,
            error_message: error
                .reason
                .map(|reason| format!("message: {}, reason: {}", error.message, reason))
                .or(Some(error.message)),
            error_code: Some(error.code),
        },
    };
    state
        .store
        .update_authentication_by_merchant_id_authentication_id(
            authentication,
            authentication_update,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Error while updating authentication")
}


/// This is the url to which the customer will be redirected to, after completing the redirection flow
    pub fn create_finish_redirection_url(
        &self,
        base_url: &str,
        publishable_key: &str,
    ) -> CustomResult<url::Url, errors::api_error_response::ApiErrorResponse> {
        let finish_redirection_url = format!(
            "{base_url}/v2/payments/{}/finish-redirection/{publishable_key}/{}",
            self.id.get_string_repr(),
            self.profile_id.get_string_repr()
        );

        url::Url::parse(&finish_redirection_url)
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Error creating finish redirection url")
    }


impl PayoutLink {
    pub async fn update_payout_link(
        self,
        conn: &PgPooledConn,
        payout_link_update: PayoutLinkUpdate,
    ) -> StorageResult<Self> {
        generics::generic_update_with_results::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::link_id.eq(self.link_id.to_owned()),
            GenericLinkUpdateInternal::from(payout_link_update),
        )
        .await
        .and_then(|mut payout_links| {
            payout_links
                .pop()
                .ok_or(error_stack::report!(db_errors::DatabaseError::NotFound))
        })
        .or_else(|error| match error.current_context() {
            db_errors::DatabaseError::NoFieldsToUpdate => Ok(self),
            _ => Err(error),
        })
    }
}


pub async fn initiate_payout_link(
    _state: SessionState,
    _merchant_context: domain::MerchantContext,
    _req: payouts::PayoutLinkInitiateRequest,
    _request_headers: &header::HeaderMap,
    _locale: String,
) -> RouterResponse<services::GenericLinkFormData> {
    todo!()
}


pub struct Worldline;


pub struct TransactionDecisionData {
    external_status: TransactionStatus,
    reason: Option<String>,
    amount: StringMajorUnit,
    currency: Currency,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    decided_at: PrimitiveDateTime,
    payment_details: Vec<TransactionPaymentDetails>,
}


pub struct PayeezyCard {
    #[serde(rename = "type")]
    pub card_type: PayeezyCardType,
    pub cardholder_name: Secret<String>,
    pub card_number: CardNumber,
    pub exp_date: Secret<String>,
    pub cvv: Secret<String>,
}


impl Breadpay {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMinorUnitForConnector,
        }
    }
}


impl DynamicRoutingClientConfig {
    /// establish connection with the server
    pub fn get_dynamic_routing_connection(
        self,
        client: Client,
    ) -> Result<Option<RoutingStrategy>, Box<dyn std::error::Error>> {
        match self {
            Self::Enabled { host, port, .. } => {
                let uri = format!("http://{host}:{port}").parse::<tonic::transport::Uri>()?;
                logger::info!("Connection established with dynamic routing gRPC Server");

                let (success_rate_client, contract_based_client, elimination_based_client) = (
                    SuccessRateCalculatorClient::with_origin(client.clone(), uri.clone()),
                    ContractScoreCalculatorClient::with_origin(client.clone(), uri.clone()),
                    EliminationAnalyserClient::with_origin(client, uri),
                );

                Ok(Some(RoutingStrategy {
                    success_rate_client,
                    contract_based_client,
                    elimination_based_client,
                }))
            }
            Self::Disabled => Ok(None),
        }
    }
}


impl Analytics {
        #[cfg(feature = "v2")]
        pub fn server(state: AppState) -> Scope {
            web::scope("/analytics").app_data(web::Data::new(state))
        }
        #[cfg(feature = "v1")]
        pub fn server(state: AppState) -> Scope {
            web::scope("/analytics")
                .app_data(web::Data::new(state))
                .service(
                    web::scope("/v1")
                        .service(
                            web::resource("metrics/payments")
                                .route(web::post().to(get_merchant_payment_metrics)),
                        )
                        .service(
                            web::resource("metrics/routing")
                                .route(web::post().to(get_merchant_payment_metrics)),
                        )
                        .service(
                            web::resource("metrics/refunds")
                                .route(web::post().to(get_merchant_refund_metrics)),
                        )
                        .service(
                            web::resource("filters/payments")
                                .route(web::post().to(get_merchant_payment_filters)),
                        )
                        .service(
                            web::resource("filters/routing")
                                .route(web::post().to(get_merchant_payment_filters)),
                        )
                        .service(
                            web::resource("filters/frm").route(web::post().to(get_frm_filters)),
                        )
                        .service(
                            web::resource("filters/refunds")
                                .route(web::post().to(get_merchant_refund_filters)),
                        )
                        .service(web::resource("{domain}/info").route(web::get().to(get_info)))
                        .service(
                            web::resource("report/dispute")
                                .route(web::post().to(generate_merchant_dispute_report)),
                        )
                        .service(
                            web::resource("report/refunds")
                                .route(web::post().to(generate_merchant_refund_report)),
                        )
                        .service(
                            web::resource("report/payments")
                                .route(web::post().to(generate_merchant_payment_report)),
                        )
                        .service(
                            web::resource("report/authentications")
                                .route(web::post().to(generate_merchant_authentication_report)),
                        )
                        .service(
                            web::resource("metrics/sdk_events")
                                .route(web::post().to(get_sdk_event_metrics)),
                        )
                        .service(
                            web::resource("metrics/active_payments")
                                .route(web::post().to(get_active_payments_metrics)),
                        )
                        .service(
                            web::resource("filters/sdk_events")
                                .route(web::post().to(get_sdk_event_filters)),
                        )
                        .service(
                            web::resource("metrics/auth_events")
                                .route(web::post().to(get_merchant_auth_event_metrics)),
                        )
                        .service(
                            web::resource("filters/auth_events")
                                .route(web::post().to(get_merchant_auth_events_filters)),
                        )
                        .service(
                            web::resource("metrics/frm").route(web::post().to(get_frm_metrics)),
                        )
                        .service(
                            web::resource("api_event_logs")
                                .route(web::get().to(get_profile_api_events)),
                        )
                        .service(
                            web::resource("sdk_event_logs")
                                .route(web::post().to(get_profile_sdk_events)),
                        )
                        .service(
                            web::resource("connector_event_logs")
                                .route(web::get().to(get_profile_connector_events)),
                        )
                        .service(
                            web::resource("routing_event_logs")
                                .route(web::get().to(get_profile_routing_events)),
                        )
                        .service(
                            web::resource("outgoing_webhook_event_logs")
                                .route(web::get().to(get_profile_outgoing_webhook_events)),
                        )
                        .service(
                            web::resource("metrics/api_events")
                                .route(web::post().to(get_merchant_api_events_metrics)),
                        )
                        .service(
                            web::resource("filters/api_events")
                                .route(web::post().to(get_merchant_api_event_filters)),
                        )
                        .service(
                            web::resource("search")
                                .route(web::post().to(get_global_search_results)),
                        )
                        .service(
                            web::resource("search/{domain}")
                                .route(web::post().to(get_search_results)),
                        )
                        .service(
                            web::resource("metrics/disputes")
                                .route(web::post().to(get_merchant_dispute_metrics)),
                        )
                        .service(
                            web::resource("filters/disputes")
                                .route(web::post().to(get_merchant_dispute_filters)),
                        )
                        .service(
                            web::resource("metrics/sankey")
                                .route(web::post().to(get_merchant_sankey)),
                        )
                        .service(
                            web::resource("metrics/auth_events/sankey")
                                .route(web::post().to(get_merchant_auth_event_sankey)),
                        )
                        .service(
                            web::scope("/merchant")
                                .service(
                                    web::resource("metrics/payments")
                                        .route(web::post().to(get_merchant_payment_metrics)),
                                )
                                .service(
                                    web::resource("metrics/routing")
                                        .route(web::post().to(get_merchant_payment_metrics)),
                                )
                                .service(
                                    web::resource("metrics/refunds")
                                        .route(web::post().to(get_merchant_refund_metrics)),
                                )
                                .service(
                                    web::resource("metrics/auth_events")
                                        .route(web::post().to(get_merchant_auth_event_metrics)),
                                )
                                .service(
                                    web::resource("filters/payments")
                                        .route(web::post().to(get_merchant_payment_filters)),
                                )
                                .service(
                                    web::resource("filters/routing")
                                        .route(web::post().to(get_merchant_payment_filters)),
                                )
                                .service(
                                    web::resource("filters/refunds")
                                        .route(web::post().to(get_merchant_refund_filters)),
                                )
                                .service(
                                    web::resource("filters/auth_events")
                                        .route(web::post().to(get_merchant_auth_events_filters)),
                                )
                                .service(
                                    web::resource("{domain}/info").route(web::get().to(get_info)),
                                )
                                .service(
                                    web::resource("report/dispute")
                                        .route(web::post().to(generate_merchant_dispute_report)),
                                )
                                .service(
                                    web::resource("report/refunds")
                                        .route(web::post().to(generate_merchant_refund_report)),
                                )
                                .service(
                                    web::resource("report/payments")
                                        .route(web::post().to(generate_merchant_payment_report)),
                                )
                                .service(
                                    web::resource("report/authentications").route(
                                        web::post().to(generate_merchant_authentication_report),
                                    ),
                                )
                                .service(
                                    web::resource("metrics/api_events")
                                        .route(web::post().to(get_merchant_api_events_metrics)),
                                )
                                .service(
                                    web::resource("filters/api_events")
                                        .route(web::post().to(get_merchant_api_event_filters)),
                                )
                                .service(
                                    web::resource("metrics/disputes")
                                        .route(web::post().to(get_merchant_dispute_metrics)),
                                )
                                .service(
                                    web::resource("filters/disputes")
                                        .route(web::post().to(get_merchant_dispute_filters)),
                                )
                                .service(
                                    web::resource("metrics/sankey")
                                        .route(web::post().to(get_merchant_sankey)),
                                )
                                .service(
                                    web::resource("metrics/auth_events/sankey")
                                        .route(web::post().to(get_merchant_auth_event_sankey)),
                                ),
                        )
                        .service(
                            web::scope("/org")
                                .service(
                                    web::resource("{domain}/info").route(web::get().to(get_info)),
                                )
                                .service(
                                    web::resource("metrics/payments")
                                        .route(web::post().to(get_org_payment_metrics)),
                                )
                                .service(
                                    web::resource("filters/payments")
                                        .route(web::post().to(get_org_payment_filters)),
                                )
                                .service(
                                    web::resource("metrics/routing")
                                        .route(web::post().to(get_org_payment_metrics)),
                                )
                                .service(
                                    web::resource("filters/routing")
                                        .route(web::post().to(get_org_payment_filters)),
                                )
                                .service(
                                    web::resource("metrics/refunds")
                                        .route(web::post().to(get_org_refund_metrics)),
                                )
                                .service(
                                    web::resource("filters/refunds")
                                        .route(web::post().to(get_org_refund_filters)),
                                )
                                .service(
                                    web::resource("metrics/disputes")
                                        .route(web::post().to(get_org_dispute_metrics)),
                                )
                                .service(
                                    web::resource("metrics/auth_events")
                                        .route(web::post().to(get_org_auth_event_metrics)),
                                )
                                .service(
                                    web::resource("filters/disputes")
                                        .route(web::post().to(get_org_dispute_filters)),
                                )
                                .service(
                                    web::resource("filters/auth_events")
                                        .route(web::post().to(get_org_auth_events_filters)),
                                )
                                .service(
                                    web::resource("report/dispute")
                                        .route(web::post().to(generate_org_dispute_report)),
                                )
                                .service(
                                    web::resource("report/refunds")
                                        .route(web::post().to(generate_org_refund_report)),
                                )
                                .service(
                                    web::resource("report/payments")
                                        .route(web::post().to(generate_org_payment_report)),
                                )
                                .service(
                                    web::resource("report/authentications")
                                        .route(web::post().to(generate_org_authentication_report)),
                                )
                                .service(
                                    web::resource("metrics/sankey")
                                        .route(web::post().to(get_org_sankey)),
                                )
                                .service(
                                    web::resource("metrics/auth_events/sankey")
                                        .route(web::post().to(get_org_auth_event_sankey)),
                                ),
                        )
                        .service(
                            web::scope("/profile")
                                .service(
                                    web::resource("{domain}/info").route(web::get().to(get_info)),
                                )
                                .service(
                                    web::resource("metrics/payments")
                                        .route(web::post().to(get_profile_payment_metrics)),
                                )
                                .service(
                                    web::resource("filters/payments")
                                        .route(web::post().to(get_profile_payment_filters)),
                                )
                                .service(
                                    web::resource("metrics/routing")
                                        .route(web::post().to(get_profile_payment_metrics)),
                                )
                                .service(
                                    web::resource("filters/routing")
                                        .route(web::post().to(get_profile_payment_filters)),
                                )
                                .service(
                                    web::resource("metrics/refunds")
                                        .route(web::post().to(get_profile_refund_metrics)),
                                )
                                .service(
                                    web::resource("filters/refunds")
                                        .route(web::post().to(get_profile_refund_filters)),
                                )
                                .service(
                                    web::resource("metrics/disputes")
                                        .route(web::post().to(get_profile_dispute_metrics)),
                                )
                                .service(
                                    web::resource("metrics/auth_events")
                                        .route(web::post().to(get_profile_auth_event_metrics)),
                                )
                                .service(
                                    web::resource("filters/disputes")
                                        .route(web::post().to(get_profile_dispute_filters)),
                                )
                                .service(
                                    web::resource("filters/auth_events")
                                        .route(web::post().to(get_profile_auth_events_filters)),
                                )
                                .service(
                                    web::resource("connector_event_logs")
                                        .route(web::get().to(get_profile_connector_events)),
                                )
                                .service(
                                    web::resource("routing_event_logs")
                                        .route(web::get().to(get_profile_routing_events)),
                                )
                                .service(
                                    web::resource("outgoing_webhook_event_logs")
                                        .route(web::get().to(get_profile_outgoing_webhook_events)),
                                )
                                .service(
                                    web::resource("report/dispute")
                                        .route(web::post().to(generate_profile_dispute_report)),
                                )
                                .service(
                                    web::resource("report/refunds")
                                        .route(web::post().to(generate_profile_refund_report)),
                                )
                                .service(
                                    web::resource("report/payments")
                                        .route(web::post().to(generate_profile_payment_report)),
                                )
                                .service(
                                    web::resource("report/authentications").route(
                                        web::post().to(generate_profile_authentication_report),
                                    ),
                                )
                                .service(
                                    web::resource("api_event_logs")
                                        .route(web::get().to(get_profile_api_events)),
                                )
                                .service(
                                    web::resource("sdk_event_logs")
                                        .route(web::post().to(get_profile_sdk_events)),
                                )
                                .service(
                                    web::resource("metrics/sankey")
                                        .route(web::post().to(get_profile_sankey)),
                                )
                                .service(
                                    web::resource("metrics/auth_events/sankey")
                                        .route(web::post().to(get_profile_auth_event_sankey)),
                                ),
                        ),
                )
                .service(
                    web::scope("/v2")
                        .service(
                            web::resource("/metrics/payments")
                                .route(web::post().to(get_merchant_payment_intent_metrics)),
                        )
                        .service(
                            web::resource("/filters/payments")
                                .route(web::post().to(get_payment_intents_filters)),
                        )
                        .service(
                            web::scope("/merchant")
                                .service(
                                    web::resource("/metrics/payments")
                                        .route(web::post().to(get_merchant_payment_intent_metrics)),
                                )
                                .service(
                                    web::resource("/filters/payments")
                                        .route(web::post().to(get_payment_intents_filters)),
                                ),
                        )
                        .service(
                            web::scope("/org").service(
                                web::resource("/metrics/payments")
                                    .route(web::post().to(get_org_payment_intent_metrics)),
                            ),
                        )
                        .service(
                            web::scope("/profile").service(
                                web::resource("/metrics/payments")
                                    .route(web::post().to(get_profile_payment_intent_metrics)),
                            ),
                        ),
                )
        }
    }


pub async fn get_merchant_bank_data_for_open_banking_connectors(
    merchant_connector_account: &helpers::MerchantConnectorAccountType,
    merchant_context: &domain::MerchantContext,
    connector: &api::ConnectorData,
    state: &SessionState,
) -> RouterResult<Option<router_types::MerchantRecipientData>> {
    let merchant_data = merchant_connector_account
        .get_additional_merchant_data()
        .get_required_value("additional_merchant_data")?
        .into_inner()
        .peek()
        .clone();

    let merchant_recipient_data = merchant_data
        .parse_value::<router_types::AdditionalMerchantData>("AdditionalMerchantData")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("failed to decode MerchantRecipientData")?;

    let connector_name = enums::Connector::to_string(&connector.connector_name);
    let locker_based_connector_list = state.conf.locker_based_open_banking_connectors.clone();
    let contains = locker_based_connector_list
        .connector_list
        .contains(connector_name.as_str());

    let recipient_id = helpers::get_recipient_id_for_open_banking(&merchant_recipient_data)?;
    let final_recipient_data = if let Some(id) = recipient_id {
        if contains {
            // Customer Id for OpenBanking connectors will be merchant_id as the account data stored at locker belongs to the merchant
            let merchant_id_str = merchant_context
                .get_merchant_account()
                .get_id()
                .get_string_repr()
                .to_owned();
            let cust_id = id_type::CustomerId::try_from(std::borrow::Cow::from(merchant_id_str))
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to convert to CustomerId")?;
            let locker_resp = cards::get_payment_method_from_hs_locker(
                state,
                merchant_context.get_merchant_key_store(),
                &cust_id,
                merchant_context.get_merchant_account().get_id(),
                id.as_str(),
                Some(enums::LockerChoice::HyperswitchCardVault),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Merchant bank account data could not be fetched from locker")?;

            let parsed: router_types::MerchantAccountData = locker_resp
                .peek()
                .to_string()
                .parse_struct("MerchantAccountData")
                .change_context(errors::ApiErrorResponse::InternalServerError)?;

            Some(router_types::MerchantRecipientData::AccountData(parsed))
        } else {
            Some(router_types::MerchantRecipientData::ConnectorRecipientId(
                Secret::new(id),
            ))
        }
    } else {
        None
    };
    Ok(final_recipient_data)
}


pub fn update_algorithm_id(
        &mut self,
        new_id: common_utils::id_type::RoutingId,
        enabled_feature: DynamicRoutingFeatures,
        dynamic_routing_type: DynamicRoutingType,
    ) {
        match dynamic_routing_type {
            DynamicRoutingType::SuccessRateBasedRouting => {
                self.success_based_algorithm = Some(SuccessBasedAlgorithm {
                    algorithm_id_with_timestamp: DynamicAlgorithmWithTimestamp::new(Some(new_id)),
                    enabled_feature,
                })
            }
            DynamicRoutingType::EliminationRouting => {
                self.elimination_routing_algorithm = Some(EliminationRoutingAlgorithm {
                    algorithm_id_with_timestamp: DynamicAlgorithmWithTimestamp::new(Some(new_id)),
                    enabled_feature,
                })
            }
            DynamicRoutingType::ContractBasedRouting => {
                self.contract_based_routing = Some(ContractRoutingAlgorithm {
                    algorithm_id_with_timestamp: DynamicAlgorithmWithTimestamp::new(Some(new_id)),
                    enabled_feature,
                })
            }
        };
    }


pub struct TokenizedCardValue2 {
    pub card_security_code: Option<String>,
    pub card_fingerprint: Option<String>,
    pub external_id: Option<String>,
    pub customer_id: Option<id_type::CustomerId>,
    pub payment_method_id: Option<String>,
}


impl api::MandateSetup for Paybox {}


pub fn get_authentication_connector_config(
        connector: AuthenticationConnectors,
    ) -> Result<Option<ConnectorTomlConfig>, String> {
        let connector_data = Self::new()?;
        match connector {
            AuthenticationConnectors::Threedsecureio => Ok(connector_data.threedsecureio),
            AuthenticationConnectors::Netcetera => Ok(connector_data.netcetera),
            AuthenticationConnectors::Gpayments => Ok(connector_data.gpayments),
            AuthenticationConnectors::CtpMastercard => Ok(connector_data.ctp_mastercard),
            AuthenticationConnectors::CtpVisa => Ok(connector_data.ctp_visa),
            AuthenticationConnectors::UnifiedAuthenticationService => {
                Ok(connector_data.unified_authentication_service)
            }
            AuthenticationConnectors::Juspaythreedsserver => Ok(connector_data.juspaythreedsserver),
        }
    }