File: crates/router/src/core/payments/flows/setup_mandate_flow.rs
 Public functions: 1

use async_trait::async_trait;
use common_types::payments as common_payments_types;
use error_stack::ResultExt;
use router_env::logger;
use unified_connector_service_client::payments as payments_grpc;

use super::{ConstructFlowSpecificData, Feature};
use crate::{
    core::{
        errors::{ApiErrorResponse, ConnectorErrorExt, RouterResult},
        mandate,
        payments::{
            self, access_token, customers, helpers, tokenization, transformers, PaymentData,
        },
        unified_connector_service::{
            build_unified_connector_service_auth_metadata,
            handle_unified_connector_service_response_for_payment_register, ucs_logging_wrapper,
        },
    },
    routes::SessionState,
    services,
    types::{
        self, api, domain,
        transformers::{ForeignFrom, ForeignTryFrom},
    },
};

#[cfg(feature = "v1")]
#[async_trait]
impl
    ConstructFlowSpecificData<
        api::SetupMandate,
        types::SetupMandateRequestData,
        types::PaymentsResponseData,
    > for PaymentData<api::SetupMandate>
{
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &helpers::MerchantConnectorAccountType,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<types::SetupMandateRouterData> {
        Box::pin(transformers::construct_payment_router_data::<
            api::SetupMandate,
            types::SetupMandateRequestData,
        >(
            state,
            self.clone(),
            connector_id,
            merchant_context,
            customer,
            merchant_connector_account,
            merchant_recipient_data,
            header_payload,
        ))
        .await
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl
    ConstructFlowSpecificData<
        api::SetupMandate,
        types::SetupMandateRequestData,
        types::PaymentsResponseData,
    > for hyperswitch_domain_models::payments::PaymentConfirmData<api::SetupMandate>
{
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<types::SetupMandateRouterData> {
        Box::pin(
            transformers::construct_payment_router_data_for_setup_mandate(
                state,
                self.clone(),
                connector_id,
                merchant_context,
                customer,
                merchant_connector_account,
                merchant_recipient_data,
                header_payload,
            ),
        )
        .await
    }
}

#[async_trait]
impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::SetupMandateRouterData {
    async fn decide_flows<'a>(
        mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
        connector_request: Option<services::Request>,
        _business_profile: &domain::Profile,
        _header_payload: hyperswitch_domain_models::payments::HeaderPayload,
        _return_raw_connector_response: Option<bool>,
    ) -> RouterResult<Self> {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::SetupMandate,
            types::SetupMandateRequestData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();
        // Change the authentication_type to ThreeDs, for google_pay wallet if card_holder_authenticated or account_verified in assurance_details is false
        if let hyperswitch_domain_models::payment_method_data::PaymentMethodData::Wallet(
            hyperswitch_domain_models::payment_method_data::WalletData::GooglePay(google_pay_data),
        ) = &self.request.payment_method_data
        {
            if let Some(assurance_details) = google_pay_data.info.assurance_details.as_ref() {
                // Step up the transaction to 3DS when either assurance_details.card_holder_authenticated or assurance_details.account_verified is false
                if !assurance_details.card_holder_authenticated
                    || !assurance_details.account_verified
                {
                    logger::info!("Googlepay transaction stepped up to 3DS");
                    self.auth_type = diesel_models::enums::AuthenticationType::ThreeDs;
                }
            }
        }
        let resp = services::execute_connector_processing_step(
            state,
            connector_integration,
            &self,
            call_connector_action.clone(),
            connector_request,
            None,
        )
        .await
        .to_setup_mandate_failed_response()?;
        Ok(resp)
    }

    async fn add_access_token<'a>(
        &self,
        state: &SessionState,
        connector: &api::ConnectorData,
        merchant_context: &domain::MerchantContext,
        creds_identifier: Option<&str>,
    ) -> RouterResult<types::AddAccessTokenResult> {
        Box::pin(access_token::add_access_token(
            state,
            connector,
            merchant_context,
            self,
            creds_identifier,
        ))
        .await
    }

    async fn add_session_token<'a>(
        self,
        state: &SessionState,
        connector: &api::ConnectorData,
    ) -> RouterResult<Self>
    where
        Self: Sized,
    {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::AuthorizeSessionToken,
            types::AuthorizeSessionTokenData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();
        let authorize_data = &types::PaymentsAuthorizeSessionTokenRouterData::foreign_from((
            &self,
            types::AuthorizeSessionTokenData::foreign_from(&self),
        ));
        let resp = services::execute_connector_processing_step(
            state,
            connector_integration,
            authorize_data,
            payments::CallConnectorAction::Trigger,
            None,
            None,
        )
        .await
        .to_payment_failed_response()?;
        let mut router_data = self;
        router_data.session_token = resp.session_token;
        Ok(router_data)
    }

    async fn add_payment_method_token<'a>(
        &mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        tokenization_action: &payments::TokenizationAction,
        should_continue_payment: bool,
    ) -> RouterResult<types::PaymentMethodTokenResult> {
        let request = self.request.clone();
        tokenization::add_payment_method_token(
            state,
            connector,
            tokenization_action,
            self,
            types::PaymentMethodTokenizationData::try_from(request)?,
            should_continue_payment,
        )
        .await
    }

    async fn create_connector_customer<'a>(
        &self,
        state: &SessionState,
        connector: &api::ConnectorData,
    ) -> RouterResult<Option<String>> {
        customers::create_connector_customer(
            state,
            connector,
            self,
            types::ConnectorCustomerData::try_from(self.request.to_owned())?,
        )
        .await
    }

    async fn build_flow_specific_connector_request(
        &mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
    ) -> RouterResult<(Option<services::Request>, bool)> {
        match call_connector_action {
            payments::CallConnectorAction::Trigger => {
                let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
                    api::SetupMandate,
                    types::SetupMandateRequestData,
                    types::PaymentsResponseData,
                > = connector.connector.get_connector_integration();

                Ok((
                    connector_integration
                        .build_request(self, &state.conf.connectors)
                        .to_payment_failed_response()?,
                    true,
                ))
            }
            _ => Ok((None, true)),
        }
    }

    async fn preprocessing_steps<'a>(
        self,
        state: &SessionState,
        connector: &api::ConnectorData,
    ) -> RouterResult<Self> {
        setup_mandate_preprocessing_steps(state, &self, true, connector).await
    }

    async fn call_unified_connector_service<'a>(
        &mut self,
        state: &SessionState,
        #[cfg(feature = "v1")] merchant_connector_account: helpers::MerchantConnectorAccountType,
        #[cfg(feature = "v2")]
        merchant_connector_account: domain::MerchantConnectorAccountTypeDetails,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<()> {
        let client = state
            .grpc_client
            .unified_connector_service_client
            .clone()
            .ok_or(ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to fetch Unified Connector Service client")?;

        let payment_register_request =
            payments_grpc::PaymentServiceRegisterRequest::foreign_try_from(&*self)
                .change_context(ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to construct Payment Setup Mandate Request")?;

        let connector_auth_metadata = build_unified_connector_service_auth_metadata(
            merchant_connector_account,
            merchant_context,
        )
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to construct request metadata")?;

        let updated_router_data = Box::pin(ucs_logging_wrapper(
            self.clone(),
            state,
            payment_register_request,
            |mut router_data, payment_register_request| async move {
                let response = client
                    .payment_setup_mandate(
                        payment_register_request,
                        connector_auth_metadata,
                        state.get_grpc_headers(),
                    )
                    .await
                    .change_context(ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to Setup Mandate payment")?;

                let payment_register_response = response.into_inner();

                let (status, router_data_response, status_code) =
                    handle_unified_connector_service_response_for_payment_register(
                        payment_register_response.clone(),
                    )
                    .change_context(ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to deserialize UCS response")?;

                router_data.status = status;
                router_data.response = router_data_response;
                router_data.connector_http_status_code = Some(status_code);

                Ok((router_data, payment_register_response))
            },
        ))
        .await?;

        // Copy back the updated data
        *self = updated_router_data;
        Ok(())
    }
}

impl mandate::MandateBehaviour for types::SetupMandateRequestData {
    fn get_amount(&self) -> i64 {
        0
    }

    fn get_setup_future_usage(&self) -> Option<diesel_models::enums::FutureUsage> {
        self.setup_future_usage
    }

    fn get_mandate_id(&self) -> Option<&api_models::payments::MandateIds> {
        self.mandate_id.as_ref()
    }

    fn set_mandate_id(&mut self, new_mandate_id: Option<api_models::payments::MandateIds>) {
        self.mandate_id = new_mandate_id;
    }

    fn get_payment_method_data(&self) -> domain::payments::PaymentMethodData {
        self.payment_method_data.clone()
    }

    fn get_setup_mandate_details(
        &self,
    ) -> Option<&hyperswitch_domain_models::mandates::MandateData> {
        self.setup_mandate_details.as_ref()
    }
    fn get_customer_acceptance(&self) -> Option<common_payments_types::CustomerAcceptance> {
        self.customer_acceptance.clone()
    }
}

pub async fn setup_mandate_preprocessing_steps<F: Clone>(
    state: &SessionState,
    router_data: &types::RouterData<F, types::SetupMandateRequestData, types::PaymentsResponseData>,
    confirm: bool,
    connector: &api::ConnectorData,
) -> RouterResult<types::RouterData<F, types::SetupMandateRequestData, types::PaymentsResponseData>>
{
    if confirm {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::PreProcessing,
            types::PaymentsPreProcessingData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();

        let preprocessing_request_data =
            types::PaymentsPreProcessingData::try_from(router_data.request.clone())?;

        let preprocessing_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> =
            Err(types::ErrorResponse::default());

        let preprocessing_router_data =
            helpers::router_data_type_conversion::<_, api::PreProcessing, _, _, _, _>(
                router_data.clone(),
                preprocessing_request_data,
                preprocessing_response_data,
            );

        let resp = services::execute_connector_processing_step(
            state,
            connector_integration,
            &preprocessing_router_data,
            payments::CallConnectorAction::Trigger,
            None,
            None,
        )
        .await
        .to_payment_failed_response()?;

        let mut setup_mandate_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>(
            resp.clone(),
            router_data.request.to_owned(),
            resp.response.clone(),
        );

        if connector.connector_name == api_models::enums::Connector::Nuvei {
            let (enrolled_for_3ds, related_transaction_id) =
                match &setup_mandate_router_data.response {
                    Ok(types::PaymentsResponseData::ThreeDSEnrollmentResponse {
                        enrolled_v2,
                        related_transaction_id,
                    }) => (*enrolled_v2, related_transaction_id.clone()),
                    _ => (false, None),
                };
            setup_mandate_router_data.request.enrolled_for_3ds = enrolled_for_3ds;
            setup_mandate_router_data.request.related_transaction_id = related_transaction_id;
        }

        Ok(setup_mandate_router_data)
    } else {
        Ok(router_data.clone())
    }
}


impl ConnectorCommon for Helcim {
    fn id(&self) -> &'static str {
        "helcim"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Base
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.helcim.base_url.as_ref()
    }

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::maskable::Maskable<String>)>, errors::ConnectorError>
    {
        let auth = helcim::HelcimAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::API_TOKEN.to_string(),
            auth.api_key.expose().into_masked(),
        )])
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: helcim::HelcimErrorResponse = res
            .response
            .parse_struct("HelcimErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_error_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        let error_string = match response {
            transformers::HelcimErrorResponse::Payment(response) => match response.errors {
                transformers::HelcimErrorTypes::StringType(error) => error,
                transformers::HelcimErrorTypes::JsonType(error) => error.to_string(),
            },
            transformers::HelcimErrorResponse::General(error_string) => error_string,
        };

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: NO_ERROR_CODE.to_owned(),
            message: error_string.clone(),
            reason: Some(error_string),
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}


pub struct FileMetadata {
    #[serde(skip_serializing)]
    pub file_id: String,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub file_name: Option<String>,
    pub file_size: i32,
    pub file_type: String,
    pub provider_file_id: Option<String>,
    pub file_upload_provider: Option<common_enums::FileUploadProvider>,
    pub available: bool,
    #[serde(with = "custom_serde::iso8601")]
    pub created_at: time::PrimitiveDateTime,
    pub connector_label: Option<String>,
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
}


pub struct RefundListRequest {
    /// The identifier for the payment
    #[schema(value_type = Option<String>)]
    pub payment_id: Option<common_utils::id_type::GlobalPaymentId>,
    /// The identifier for the refund
    #[schema(value_type = String)]
    pub refund_id: Option<common_utils::id_type::GlobalRefundId>,
    /// Limit on the number of objects to return
    pub limit: Option<i64>,
    /// The starting point within a list of objects
    pub offset: Option<i64>,
    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc)
    #[serde(flatten)]
    pub time_range: Option<TimeRange>,
    /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range)
    pub amount_filter: Option<AmountFilter>,
    /// The list of connectors to filter refunds list
    pub connector: Option<Vec<String>>,
    /// The list of merchant connector ids to filter the refunds list for selected label
    #[schema(value_type = Option<Vec<String>>)]
    pub connector_id_list: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
    /// The list of currencies to filter refunds list
    #[schema(value_type = Option<Vec<Currency>>)]
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of refund statuses to filter refunds list
    #[schema(value_type = Option<Vec<RefundStatus>>)]
    pub refund_status: Option<Vec<enums::RefundStatus>>,
}


pub struct Mandates;


pub struct RelayRequest {
    /// The identifier that is associated to a resource at the connector reference to which the relay request is being made
    #[schema(example = "7256228702616471803954")]
    pub connector_resource_id: String,
    /// Identifier of the connector ( merchant connector account ) which was chosen to make the payment
    #[schema(example = "mca_5apGeP94tMts6rg3U3kR", value_type = String)]
    pub connector_id: common_utils::id_type::MerchantConnectorAccountId,
    /// The type of relay request
    #[serde(rename = "type")]
    #[schema(value_type = RelayType)]
    pub relay_type: api_enums::RelayType,
    /// The data that is associated with the relay request
    pub data: Option<RelayData>,
}


impl api::PayoutEligibility for Wise {}

impl api::PayoutEligibility for for Wise


pub struct DeutschebankTransactionInfo {
    back_state: Option<String>,
    ip_address: Option<Secret<String>>,
    #[serde(rename = "type")]
    pm_type: Option<String>,
    transaction_bankaccount_info: Option<TransactionBankAccountInfo>,
}


pub struct EpsInfo {}


impl ExternalAuthentication for Gpayments {}

impl ExternalAuthentication for for Gpayments


impl MandateSetup for Payone {}


impl RequestBuilder {
    pub fn new() -> Self {
        Self {
            method: Method::Get,
            url: String::with_capacity(1024),
            headers: std::collections::HashSet::new(),
            certificate: None,
            certificate_key: None,
            body: None,
            ca_certificate: None,
        }
    }

    pub fn url(mut self, url: &str) -> Self {
        self.url = url.into();
        self
    }

    pub fn method(mut self, method: Method) -> Self {
        self.method = method;
        self
    }

    pub fn attach_default_headers(mut self) -> Self {
        self.headers.extend(default_request_headers());
        self
    }

    pub fn header(mut self, header: &str, value: &str) -> Self {
        self.headers.insert((header.into(), value.into()));
        self
    }

    pub fn headers(mut self, headers: Vec<(String, Maskable<String>)>) -> Self {
        self.headers.extend(headers);
        self
    }

    pub fn set_optional_body<T: Into<RequestContent>>(mut self, body: Option<T>) -> Self {
        body.map(|body| self.body.replace(body.into()));
        self
    }

    pub fn set_body<T: Into<RequestContent>>(mut self, body: T) -> Self {
        self.body.replace(body.into());
        self
    }

    pub fn add_certificate(mut self, certificate: Option<Secret<String>>) -> Self {
        self.certificate = certificate;
        self
    }

    pub fn add_certificate_key(mut self, certificate_key: Option<Secret<String>>) -> Self {
        self.certificate_key = certificate_key;
        self
    }

    pub fn add_ca_certificate_pem(mut self, ca_certificate: Option<Secret<String>>) -> Self {
        self.ca_certificate = ca_certificate;
        self
    }

    pub fn build(self) -> Request {
        Request {
            method: self.method,
            url: self.url,
            headers: self.headers,
            certificate: self.certificate,
            certificate_key: self.certificate_key,
            body: self.body,
            ca_certificate: self.ca_certificate,
        }
    }
}


pub struct Bluecode {
    amount_converter: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync),
}


pub struct Acquirer {
    pub acquirer_merchant_id: Option<String>,
    pub acquirer_bin: Option<String>,
    pub acquirer_country_code: Option<String>,
}


impl api::PayoutCancel for Ebanx {}


pub fn update_merchant_creation_status_in_decision_engine(&mut self, is_created: bool) {
        self.is_merchant_created_in_decision_engine = is_created;
    }


File: crates/hyperswitch_domain_models/src/api.rs
 Public functions: 1
 Public structs: 7

use std::{collections::HashSet, fmt::Display};

use common_utils::{
    events::{ApiEventMetric, ApiEventsType},
    impl_api_event_type,
};

use super::payment_method_data::PaymentMethodData;

#[derive(Debug, PartialEq)]
pub enum ApplicationResponse<R> {
    Json(R),
    StatusOk,
    TextPlain(String),
    JsonForRedirection(api_models::payments::RedirectionResponse),
    Form(Box<RedirectionFormData>),
    PaymentLinkForm(Box<PaymentLinkAction>),
    FileData((Vec<u8>, mime::Mime)),
    JsonWithHeaders((R, Vec<(String, masking::Maskable<String>)>)),
    GenericLinkForm(Box<GenericLinks>),
}

impl<R> ApplicationResponse<R> {
    /// Get the json response from response
    #[inline]
    pub fn get_json_body(
        self,
    ) -> common_utils::errors::CustomResult<R, common_utils::errors::ValidationError> {
        match self {
            Self::Json(body) | Self::JsonWithHeaders((body, _)) => Ok(body),
            Self::TextPlain(_)
            | Self::JsonForRedirection(_)
            | Self::Form(_)
            | Self::PaymentLinkForm(_)
            | Self::FileData(_)
            | Self::GenericLinkForm(_)
            | Self::StatusOk => Err(common_utils::errors::ValidationError::InvalidValue {
                message: "expected either Json or JsonWithHeaders Response".to_string(),
            }
            .into()),
        }
    }
}

impl<T: ApiEventMetric> ApiEventMetric for ApplicationResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        match self {
            Self::Json(r) => r.get_api_event_type(),
            Self::JsonWithHeaders((r, _)) => r.get_api_event_type(),
            _ => None,
        }
    }
}

impl_api_event_type!(Miscellaneous, (PaymentLinkFormData, GenericLinkFormData));

#[derive(Debug, PartialEq)]
pub struct RedirectionFormData {
    pub redirect_form: crate::router_response_types::RedirectForm,
    pub payment_method_data: Option<PaymentMethodData>,
    pub amount: String,
    pub currency: String,
}

#[derive(Debug, Eq, PartialEq)]
pub enum PaymentLinkAction {
    PaymentLinkFormData(PaymentLinkFormData),
    PaymentLinkStatus(PaymentLinkStatusData),
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentLinkFormData {
    pub js_script: String,
    pub css_script: String,
    pub sdk_url: url::Url,
    pub html_meta_tags: String,
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentLinkStatusData {
    pub js_script: String,
    pub css_script: String,
}

#[derive(Debug, Eq, PartialEq)]
pub struct GenericLinks {
    pub allowed_domains: HashSet<String>,
    pub data: GenericLinksData,
    pub locale: String,
}

#[derive(Debug, Eq, PartialEq)]
pub enum GenericLinksData {
    ExpiredLink(GenericExpiredLinkData),
    PaymentMethodCollect(GenericLinkFormData),
    PayoutLink(GenericLinkFormData),
    PayoutLinkStatus(GenericLinkStatusData),
    PaymentMethodCollectStatus(GenericLinkStatusData),
    SecurePaymentLink(PaymentLinkFormData),
}

impl Display for GenericLinksData {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match *self {
                Self::ExpiredLink(_) => "ExpiredLink",
                Self::PaymentMethodCollect(_) => "PaymentMethodCollect",
                Self::PayoutLink(_) => "PayoutLink",
                Self::PayoutLinkStatus(_) => "PayoutLinkStatus",
                Self::PaymentMethodCollectStatus(_) => "PaymentMethodCollectStatus",
                Self::SecurePaymentLink(_) => "SecurePaymentLink",
            }
        )
    }
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct GenericExpiredLinkData {
    pub title: String,
    pub message: String,
    pub theme: String,
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct GenericLinkFormData {
    pub js_data: String,
    pub css_data: String,
    pub sdk_url: url::Url,
    pub html_meta_tags: String,
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct GenericLinkStatusData {
    pub js_data: String,
    pub css_data: String,
}


File: crates/euclid/src/dssa.rs

//! Domain Specific Static Analyzer
pub mod analyzer;
pub mod graph;
pub mod state_machine;
pub mod truth;
pub mod types;
pub mod utils;


impl<Secret: ZeroizableSecret, MaskingStrategy> Default for StrongSecret<Secret, MaskingStrategy>
where
    Secret: ZeroizableSecret + Default,
{
    fn default() -> Self {
        Secret::default().into()
    }
}


impl api::PaymentsCompleteAuthorize for Powertranz {}

impl api::PaymentsCompleteAuthorize for for Powertranz


pub async fn set_config(state: SessionState, config: api::Config) -> RouterResponse<api::Config> {
    let store = state.store.as_ref();
    let config = store
        .insert_config(diesel_models::configs::ConfigNew {
            key: config.key,
            config: config.value,
        })
        .await
        .to_duplicate_response(errors::ApiErrorResponse::DuplicateConfig)
        .attach_printable("Unknown error, while setting config key")?;

    Ok(ApplicationResponse::Json(config.foreign_into()))
}


pub struct BlackhawknetworkRouterData<T> {
    pub amount: StringMajorUnit,
    pub router_data: T,
}


pub struct CalculateTax;


impl api::Payment for Paytm {}


pub async fn find_by_merchant_id_event_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::event_id.eq(event_id.to_owned())),
        )
        .await
    }


pub struct OpenIdConnectPrivateConfig {
    pub base_url: String,
    pub client_id: Secret<String>,
    pub client_secret: Secret<String>,
    pub private_key: Option<Secret<String>>,
}


pub async fn call_multiple_connectors_service<F, Op, Req, D>(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connectors: api::SessionConnectorDatas,
    _operation: &Op,
    mut payment_data: D,
    customer: &Option<domain::Customer>,
    session_surcharge_details: Option<api::SessionSurchargeDetails>,
    business_profile: &domain::Profile,
    header_payload: HeaderPayload,
    return_raw_connector_response: Option<bool>,
) -> RouterResult<D>
where
    Op: Debug,
    F: Send + Clone,

    // To create connector flow specific interface data
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
    D: ConstructFlowSpecificData<F, Req, router_types::PaymentsResponseData>,
    RouterData<F, Req, router_types::PaymentsResponseData>: Feature<F, Req>,

    // To construct connector flow specific api
    dyn api::Connector:
        services::api::ConnectorIntegration<F, Req, router_types::PaymentsResponseData>,
{
    let call_connectors_start_time = Instant::now();
    let mut join_handlers = Vec::with_capacity(connectors.len());
    for session_connector_data in connectors.iter() {
        let connector_id = session_connector_data.connector.connector.id();

        let merchant_connector_account = construct_profile_id_and_get_mca(
            state,
            merchant_context,
            &payment_data,
            &session_connector_data.connector.connector_name.to_string(),
            session_connector_data
                .connector
                .merchant_connector_id
                .as_ref(),
            false,
        )
        .await?;

        payment_data.set_surcharge_details(session_surcharge_details.as_ref().and_then(
            |session_surcharge_details| {
                session_surcharge_details.fetch_surcharge_details(
                    session_connector_data.payment_method_sub_type.into(),
                    session_connector_data.payment_method_sub_type,
                    None,
                )
            },
        ));

        let router_data = payment_data
            .construct_router_data(
                state,
                connector_id,
                merchant_context,
                customer,
                &merchant_connector_account,
                None,
                None,
            )
            .await?;

        let res = router_data.decide_flows(
            state,
            &session_connector_data.connector,
            CallConnectorAction::Trigger,
            None,
            business_profile,
            header_payload.clone(),
            return_raw_connector_response,
        );

        join_handlers.push(res);
    }

    let result = join_all(join_handlers).await;

    for (connector_res, session_connector) in result.into_iter().zip(connectors) {
        let connector_name = session_connector.connector.connector_name.to_string();
        match connector_res {
            Ok(connector_response) => {
                if let Ok(router_types::PaymentsResponseData::SessionResponse {
                    session_token,
                    ..
                }) = connector_response.response.clone()
                {
                    // If session token is NoSessionTokenReceived, it is not pushed into the sessions_token as there is no response or there can be some error
                    // In case of error, that error is already logged
                    if !matches!(
                        session_token,
                        api_models::payments::SessionToken::NoSessionTokenReceived,
                    ) {
                        payment_data.push_sessions_token(session_token);
                    }
                }
                if let Err(connector_error_response) = connector_response.response {
                    logger::error!(
                        "sessions_connector_error {} {:?}",
                        connector_name,
                        connector_error_response
                    );
                }
            }
            Err(api_error) => {
                logger::error!("sessions_api_error {} {:?}", connector_name, api_error);
            }
        }
    }

    // If click_to_pay is enabled and authentication_product_ids is configured in profile, we need to attach click_to_pay block in the session response for invoking click_to_pay SDK
    if business_profile.is_click_to_pay_enabled {
        if let Some(value) = business_profile.authentication_product_ids.clone() {
            let session_token = get_session_token_for_click_to_pay(
                state,
                merchant_context.get_merchant_account().get_id(),
                merchant_context,
                value,
                payment_data.get_payment_intent(),
                business_profile.get_id(),
            )
            .await?;
            payment_data.push_sessions_token(session_token);
        }
    }

    let call_connectors_end_time = Instant::now();
    let call_connectors_duration =
        call_connectors_end_time.saturating_duration_since(call_connectors_start_time);
    tracing::info!(duration = format!("Duration taken: {}", call_connectors_duration.as_millis()));

    Ok(payment_data)
}


impl webhooks::IncomingWebhook for Worldpayvantiv {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_resource_object(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }
}

impl webhooks::IncomingWebhook for for Worldpayvantiv


File: crates/kgraph_utils/src/mca.rs
 Public functions: 1

#[cfg(feature = "v1")]
use std::str::FromStr;

#[cfg(feature = "v1")]
use api_models::payment_methods::RequestPaymentMethodTypes;
use api_models::{admin as admin_api, enums as api_enums, refunds::MinorUnit};
use euclid::{
    dirval,
    frontend::{ast, dir},
    types::{NumValue, NumValueRefinement},
};
use hyperswitch_constraint_graph as cgraph;
use strum::IntoEnumIterator;

use crate::{error::KgraphError, transformers::IntoDirValue, types as kgraph_types};

pub const DOMAIN_IDENTIFIER: &str = "payment_methods_enabled_for_merchantconnectoraccount";

// #[cfg(feature = "v1")]
fn get_dir_value_payment_method(
    from: api_enums::PaymentMethodType,
) -> Result<dir::DirValue, KgraphError> {
    match from {
        api_enums::PaymentMethodType::AmazonPay => Ok(dirval!(WalletType = AmazonPay)),
        api_enums::PaymentMethodType::Skrill => Ok(dirval!(WalletType = Skrill)),
        api_enums::PaymentMethodType::Paysera => Ok(dirval!(WalletType = Paysera)),
        api_enums::PaymentMethodType::Credit => Ok(dirval!(CardType = Credit)),
        api_enums::PaymentMethodType::Debit => Ok(dirval!(CardType = Debit)),
        #[cfg(feature = "v2")]
        api_enums::PaymentMethodType::Card => Ok(dirval!(CardType = Card)),
        api_enums::PaymentMethodType::Giropay => Ok(dirval!(BankRedirectType = Giropay)),
        api_enums::PaymentMethodType::Ideal => Ok(dirval!(BankRedirectType = Ideal)),
        api_enums::PaymentMethodType::Sofort => Ok(dirval!(BankRedirectType = Sofort)),
        api_enums::PaymentMethodType::Eps => Ok(dirval!(BankRedirectType = Eps)),
        api_enums::PaymentMethodType::Eft => Ok(dirval!(BankRedirectType = Eft)),
        api_enums::PaymentMethodType::Klarna => Ok(dirval!(PayLaterType = Klarna)),
        api_enums::PaymentMethodType::Flexiti => Ok(dirval!(PayLaterType = Flexiti)),
        api_enums::PaymentMethodType::Affirm => Ok(dirval!(PayLaterType = Affirm)),
        api_enums::PaymentMethodType::AfterpayClearpay => {
            Ok(dirval!(PayLaterType = AfterpayClearpay))
        }
        api_enums::PaymentMethodType::GooglePay => Ok(dirval!(WalletType = GooglePay)),
        api_enums::PaymentMethodType::Bluecode => Ok(dirval!(WalletType = Bluecode)),
        api_enums::PaymentMethodType::ApplePay => Ok(dirval!(WalletType = ApplePay)),
        api_enums::PaymentMethodType::Paypal => Ok(dirval!(WalletType = Paypal)),
        api_enums::PaymentMethodType::CryptoCurrency => Ok(dirval!(CryptoType = CryptoCurrency)),
        api_enums::PaymentMethodType::Ach => Ok(dirval!(BankDebitType = Ach)),

        api_enums::PaymentMethodType::Bacs => Ok(dirval!(BankDebitType = Bacs)),

        api_enums::PaymentMethodType::Becs => Ok(dirval!(BankDebitType = Becs)),
        api_enums::PaymentMethodType::Sepa => Ok(dirval!(BankDebitType = Sepa)),

        api_enums::PaymentMethodType::AliPay => Ok(dirval!(WalletType = AliPay)),
        api_enums::PaymentMethodType::AliPayHk => Ok(dirval!(WalletType = AliPayHk)),
        api_enums::PaymentMethodType::BancontactCard => {
            Ok(dirval!(BankRedirectType = BancontactCard))
        }
        api_enums::PaymentMethodType::Blik => Ok(dirval!(BankRedirectType = Blik)),
        api_enums::PaymentMethodType::MbWay => Ok(dirval!(WalletType = MbWay)),
        api_enums::PaymentMethodType::MobilePay => Ok(dirval!(WalletType = MobilePay)),
        api_enums::PaymentMethodType::Cashapp => Ok(dirval!(WalletType = Cashapp)),
        api_enums::PaymentMethodType::Multibanco => Ok(dirval!(BankTransferType = Multibanco)),
        api_enums::PaymentMethodType::Pix => Ok(dirval!(BankTransferType = Pix)),
        api_enums::PaymentMethodType::Pse => Ok(dirval!(BankTransferType = Pse)),
        api_enums::PaymentMethodType::Interac => Ok(dirval!(BankRedirectType = Interac)),
        api_enums::PaymentMethodType::OnlineBankingCzechRepublic => {
            Ok(dirval!(BankRedirectType = OnlineBankingCzechRepublic))
        }
        api_enums::PaymentMethodType::OnlineBankingFinland => {
            Ok(dirval!(BankRedirectType = OnlineBankingFinland))
        }
        api_enums::PaymentMethodType::OnlineBankingPoland => {
            Ok(dirval!(BankRedirectType = OnlineBankingPoland))
        }
        api_enums::PaymentMethodType::OnlineBankingSlovakia => {
            Ok(dirval!(BankRedirectType = OnlineBankingSlovakia))
        }
        api_enums::PaymentMethodType::Swish => Ok(dirval!(WalletType = Swish)),
        api_enums::PaymentMethodType::Trustly => Ok(dirval!(BankRedirectType = Trustly)),
        api_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)),

        api_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)),
        api_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)),
        api_enums::PaymentMethodType::Przelewy24 => Ok(dirval!(BankRedirectType = Przelewy24)),
        api_enums::PaymentMethodType::WeChatPay => Ok(dirval!(WalletType = WeChatPay)),

        api_enums::PaymentMethodType::ClassicReward => Ok(dirval!(RewardType = ClassicReward)),
        api_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
        api_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
        api_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
        api_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
        api_enums::PaymentMethodType::Twint => Ok(dirval!(WalletType = Twint)),
        api_enums::PaymentMethodType::Gcash => Ok(dirval!(WalletType = Gcash)),
        api_enums::PaymentMethodType::Vipps => Ok(dirval!(WalletType = Vipps)),
        api_enums::PaymentMethodType::Momo => Ok(dirval!(WalletType = Momo)),
        api_enums::PaymentMethodType::Alma => Ok(dirval!(PayLaterType = Alma)),
        api_enums::PaymentMethodType::Dana => Ok(dirval!(WalletType = Dana)),
        api_enums::PaymentMethodType::OnlineBankingFpx => {
            Ok(dirval!(BankRedirectType = OnlineBankingFpx))
        }
        api_enums::PaymentMethodType::OnlineBankingThailand => {
            Ok(dirval!(BankRedirectType = OnlineBankingThailand))
        }
        api_enums::PaymentMethodType::LocalBankRedirect => {
            Ok(dirval!(BankRedirectType = LocalBankRedirect))
        }
        api_enums::PaymentMethodType::TouchNGo => Ok(dirval!(WalletType = TouchNGo)),
        api_enums::PaymentMethodType::Atome => Ok(dirval!(PayLaterType = Atome)),
        api_enums::PaymentMethodType::Boleto => Ok(dirval!(VoucherType = Boleto)),
        api_enums::PaymentMethodType::Efecty => Ok(dirval!(VoucherType = Efecty)),
        api_enums::PaymentMethodType::PagoEfectivo => Ok(dirval!(VoucherType = PagoEfectivo)),
        api_enums::PaymentMethodType::RedCompra => Ok(dirval!(VoucherType = RedCompra)),
        api_enums::PaymentMethodType::RedPagos => Ok(dirval!(VoucherType = RedPagos)),
        api_enums::PaymentMethodType::Alfamart => Ok(dirval!(VoucherType = Alfamart)),
        api_enums::PaymentMethodType::BcaBankTransfer => {
            Ok(dirval!(BankTransferType = BcaBankTransfer))
        }
        api_enums::PaymentMethodType::BniVa => Ok(dirval!(BankTransferType = BniVa)),
        api_enums::PaymentMethodType::BriVa => Ok(dirval!(BankTransferType = BriVa)),
        api_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)),
        api_enums::PaymentMethodType::CimbVa => Ok(dirval!(BankTransferType = CimbVa)),
        api_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)),
        api_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)),
        api_enums::PaymentMethodType::MandiriVa => Ok(dirval!(BankTransferType = MandiriVa)),
        api_enums::PaymentMethodType::LocalBankTransfer => {
            Ok(dirval!(BankTransferType = LocalBankTransfer))
        }
        api_enums::PaymentMethodType::InstantBankTransfer => {
            Ok(dirval!(BankTransferType = InstantBankTransfer))
        }
        api_enums::PaymentMethodType::InstantBankTransferFinland => {
            Ok(dirval!(BankTransferType = InstantBankTransferFinland))
        }
        api_enums::PaymentMethodType::InstantBankTransferPoland => {
            Ok(dirval!(BankTransferType = InstantBankTransferPoland))
        }
        api_enums::PaymentMethodType::SepaBankTransfer => {
            Ok(dirval!(BankTransferType = SepaBankTransfer))
        }
        api_enums::PaymentMethodType::PermataBankTransfer => {
            Ok(dirval!(BankTransferType = PermataBankTransfer))
        }
        api_enums::PaymentMethodType::IndonesianBankTransfer => {
            Ok(dirval!(BankTransferType = IndonesianBankTransfer))
        }
        api_enums::PaymentMethodType::PaySafeCard => Ok(dirval!(GiftCardType = PaySafeCard)),
        api_enums::PaymentMethodType::SevenEleven => Ok(dirval!(VoucherType = SevenEleven)),
        api_enums::PaymentMethodType::Lawson => Ok(dirval!(VoucherType = Lawson)),
        api_enums::PaymentMethodType::MiniStop => Ok(dirval!(VoucherType = MiniStop)),
        api_enums::PaymentMethodType::FamilyMart => Ok(dirval!(VoucherType = FamilyMart)),
        api_enums::PaymentMethodType::Seicomart => Ok(dirval!(VoucherType = Seicomart)),
        api_enums::PaymentMethodType::PayEasy => Ok(dirval!(VoucherType = PayEasy)),
        api_enums::PaymentMethodType::Givex => Ok(dirval!(GiftCardType = Givex)),
        api_enums::PaymentMethodType::BhnCardNetwork => Ok(dirval!(GiftCardType = BhnCardNetwork)),
        api_enums::PaymentMethodType::Benefit => Ok(dirval!(CardRedirectType = Benefit)),
        api_enums::PaymentMethodType::Knet => Ok(dirval!(CardRedirectType = Knet)),
        api_enums::PaymentMethodType::OpenBankingUk => {
            Ok(dirval!(BankRedirectType = OpenBankingUk))
        }
        api_enums::PaymentMethodType::MomoAtm => Ok(dirval!(CardRedirectType = MomoAtm)),
        api_enums::PaymentMethodType::Oxxo => Ok(dirval!(VoucherType = Oxxo)),
        api_enums::PaymentMethodType::CardRedirect => Ok(dirval!(CardRedirectType = CardRedirect)),
        api_enums::PaymentMethodType::Venmo => Ok(dirval!(WalletType = Venmo)),
        api_enums::PaymentMethodType::UpiIntent => Ok(dirval!(UpiType = UpiIntent)),
        api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
        api_enums::PaymentMethodType::Mifinity => Ok(dirval!(WalletType = Mifinity)),
        api_enums::PaymentMethodType::Fps => Ok(dirval!(RealTimePaymentType = Fps)),
        api_enums::PaymentMethodType::DuitNow => Ok(dirval!(RealTimePaymentType = DuitNow)),
        api_enums::PaymentMethodType::PromptPay => Ok(dirval!(RealTimePaymentType = PromptPay)),
        api_enums::PaymentMethodType::VietQr => Ok(dirval!(RealTimePaymentType = VietQr)),
        api_enums::PaymentMethodType::OpenBankingPIS => {
            Ok(dirval!(OpenBankingType = OpenBankingPIS))
        }
        api_enums::PaymentMethodType::Paze => Ok(dirval!(WalletType = Paze)),
        api_enums::PaymentMethodType::DirectCarrierBilling => {
            Ok(dirval!(MobilePaymentType = DirectCarrierBilling))
        }
        api_enums::PaymentMethodType::RevolutPay => Ok(dirval!(WalletType = RevolutPay)),
    }
}

#[cfg(feature = "v2")]
fn compile_request_pm_types(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    pm_types: common_types::payment_methods::RequestPaymentMethodTypes,
    pm: api_enums::PaymentMethod,
) -> Result<cgraph::NodeId, KgraphError> {
    let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

    let pmt_info = "PaymentMethodType";
    let pmt_id = builder.make_value_node(
        (pm_types.payment_method_subtype, pm)
            .into_dir_value()
            .map(Into::into)?,
        Some(pmt_info),
        None::<()>,
    );
    agg_nodes.push((
        pmt_id,
        cgraph::Relation::Positive,
        match pm_types.payment_method_subtype {
            api_enums::PaymentMethodType::Credit | api_enums::PaymentMethodType::Debit => {
                cgraph::Strength::Weak
            }

            _ => cgraph::Strength::Strong,
        },
    ));

    if let Some(card_networks) = pm_types.card_networks {
        if !card_networks.is_empty() {
            let dir_vals: Vec<dir::DirValue> = card_networks
                .into_iter()
                .map(IntoDirValue::into_dir_value)
                .collect::<Result<_, _>>()?;

            let card_network_info = "Card Networks";
            let card_network_id = builder
                .make_in_aggregator(dir_vals, Some(card_network_info), None::<()>)
                .map_err(KgraphError::GraphConstructionError)?;

            agg_nodes.push((
                card_network_id,
                cgraph::Relation::Positive,
                cgraph::Strength::Weak,
            ));
        }
    }

    let currencies_data = pm_types
        .accepted_currencies
        .and_then(|accepted_currencies| match accepted_currencies {
            common_types::payment_methods::AcceptedCurrencies::EnableOnly(curr)
                if !curr.is_empty() =>
            {
                Some((
                    curr.into_iter()
                        .map(IntoDirValue::into_dir_value)
                        .collect::<Result<_, _>>()
                        .ok()?,
                    cgraph::Relation::Positive,
                ))
            }

            common_types::payment_methods::AcceptedCurrencies::DisableOnly(curr)
                if !curr.is_empty() =>
            {
                Some((
                    curr.into_iter()
                        .map(IntoDirValue::into_dir_value)
                        .collect::<Result<_, _>>()
                        .ok()?,
                    cgraph::Relation::Negative,
                ))
            }

            _ => None,
        });

    if let Some((currencies, relation)) = currencies_data {
        let accepted_currencies_info = "Accepted Currencies";
        let accepted_currencies_id = builder
            .make_in_aggregator(currencies, Some(accepted_currencies_info), None::<()>)
            .map_err(KgraphError::GraphConstructionError)?;

        agg_nodes.push((accepted_currencies_id, relation, cgraph::Strength::Strong));
    }

    let mut amount_nodes = Vec::with_capacity(2);

    if let Some(min_amt) = pm_types.minimum_amount {
        let num_val = NumValue {
            number: min_amt,
            refinement: Some(NumValueRefinement::GreaterThanEqual),
        };

        let min_amt_info = "Minimum Amount";
        let min_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(num_val).into(),
            Some(min_amt_info),
            None::<()>,
        );

        amount_nodes.push(min_amt_id);
    }

    if let Some(max_amt) = pm_types.maximum_amount {
        let num_val = NumValue {
            number: max_amt,
            refinement: Some(NumValueRefinement::LessThanEqual),
        };

        let max_amt_info = "Maximum Amount";
        let max_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(num_val).into(),
            Some(max_amt_info),
            None::<()>,
        );

        amount_nodes.push(max_amt_id);
    }

    if !amount_nodes.is_empty() {
        let zero_num_val = NumValue {
            number: MinorUnit::zero(),
            refinement: None,
        };

        let zero_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(zero_num_val).into(),
            Some("zero_amount"),
            None::<()>,
        );

        let or_node_neighbor_id = if amount_nodes.len() == 1 {
            amount_nodes
                .first()
                .copied()
                .ok_or(KgraphError::IndexingError)?
        } else {
            let nodes = amount_nodes
                .iter()
                .copied()
                .map(|node_id| {
                    (
                        node_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    )
                })
                .collect::<Vec<_>>();

            builder
                .make_all_aggregator(
                    &nodes,
                    Some("amount_constraint_aggregator"),
                    None::<()>,
                    None,
                )
                .map_err(KgraphError::GraphConstructionError)?
        };

        let any_aggregator = builder
            .make_any_aggregator(
                &[
                    (
                        zero_amt_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                    (
                        or_node_neighbor_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                ],
                Some("zero_plus_limits_amount_aggregator"),
                None::<()>,
                None,
            )
            .map_err(KgraphError::GraphConstructionError)?;

        agg_nodes.push((
            any_aggregator,
            cgraph::Relation::Positive,
            cgraph::Strength::Strong,
        ));
    }

    let pmt_all_aggregator_info = "All Aggregator for PaymentMethodType";
    builder
        .make_all_aggregator(&agg_nodes, Some(pmt_all_aggregator_info), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)
}

#[cfg(feature = "v1")]
fn compile_request_pm_types(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    pm_types: RequestPaymentMethodTypes,
    pm: api_enums::PaymentMethod,
) -> Result<cgraph::NodeId, KgraphError> {
    let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

    let pmt_info = "PaymentMethodType";
    let pmt_id = builder.make_value_node(
        (pm_types.payment_method_type, pm)
            .into_dir_value()
            .map(Into::into)?,
        Some(pmt_info),
        None::<()>,
    );
    agg_nodes.push((
        pmt_id,
        cgraph::Relation::Positive,
        match pm_types.payment_method_type {
            api_enums::PaymentMethodType::Credit | api_enums::PaymentMethodType::Debit => {
                cgraph::Strength::Weak
            }

            _ => cgraph::Strength::Strong,
        },
    ));

    if let Some(card_networks) = pm_types.card_networks {
        if !card_networks.is_empty() {
            let dir_vals: Vec<dir::DirValue> = card_networks
                .into_iter()
                .map(IntoDirValue::into_dir_value)
                .collect::<Result<_, _>>()?;

            let card_network_info = "Card Networks";
            let card_network_id = builder
                .make_in_aggregator(dir_vals, Some(card_network_info), None::<()>)
                .map_err(KgraphError::GraphConstructionError)?;

            agg_nodes.push((
                card_network_id,
                cgraph::Relation::Positive,
                cgraph::Strength::Weak,
            ));
        }
    }

    let currencies_data = pm_types
        .accepted_currencies
        .and_then(|accepted_currencies| match accepted_currencies {
            admin_api::AcceptedCurrencies::EnableOnly(curr) if !curr.is_empty() => Some((
                curr.into_iter()
                    .map(IntoDirValue::into_dir_value)
                    .collect::<Result<_, _>>()
                    .ok()?,
                cgraph::Relation::Positive,
            )),

            admin_api::AcceptedCurrencies::DisableOnly(curr) if !curr.is_empty() => Some((
                curr.into_iter()
                    .map(IntoDirValue::into_dir_value)
                    .collect::<Result<_, _>>()
                    .ok()?,
                cgraph::Relation::Negative,
            )),

            _ => None,
        });

    if let Some((currencies, relation)) = currencies_data {
        let accepted_currencies_info = "Accepted Currencies";
        let accepted_currencies_id = builder
            .make_in_aggregator(currencies, Some(accepted_currencies_info), None::<()>)
            .map_err(KgraphError::GraphConstructionError)?;

        agg_nodes.push((accepted_currencies_id, relation, cgraph::Strength::Strong));
    }

    let mut amount_nodes = Vec::with_capacity(2);

    if let Some(min_amt) = pm_types.minimum_amount {
        let num_val = NumValue {
            number: min_amt,
            refinement: Some(NumValueRefinement::GreaterThanEqual),
        };

        let min_amt_info = "Minimum Amount";
        let min_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(num_val).into(),
            Some(min_amt_info),
            None::<()>,
        );

        amount_nodes.push(min_amt_id);
    }

    if let Some(max_amt) = pm_types.maximum_amount {
        let num_val = NumValue {
            number: max_amt,
            refinement: Some(NumValueRefinement::LessThanEqual),
        };

        let max_amt_info = "Maximum Amount";
        let max_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(num_val).into(),
            Some(max_amt_info),
            None::<()>,
        );

        amount_nodes.push(max_amt_id);
    }

    if !amount_nodes.is_empty() {
        let zero_num_val = NumValue {
            number: MinorUnit::zero(),
            refinement: None,
        };

        let zero_amt_id = builder.make_value_node(
            dir::DirValue::PaymentAmount(zero_num_val).into(),
            Some("zero_amount"),
            None::<()>,
        );

        let or_node_neighbor_id = if amount_nodes.len() == 1 {
            amount_nodes
                .first()
                .copied()
                .ok_or(KgraphError::IndexingError)?
        } else {
            let nodes = amount_nodes
                .iter()
                .copied()
                .map(|node_id| {
                    (
                        node_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    )
                })
                .collect::<Vec<_>>();

            builder
                .make_all_aggregator(
                    &nodes,
                    Some("amount_constraint_aggregator"),
                    None::<()>,
                    None,
                )
                .map_err(KgraphError::GraphConstructionError)?
        };

        let any_aggregator = builder
            .make_any_aggregator(
                &[
                    (
                        zero_amt_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                    (
                        or_node_neighbor_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                ],
                Some("zero_plus_limits_amount_aggregator"),
                None::<()>,
                None,
            )
            .map_err(KgraphError::GraphConstructionError)?;

        agg_nodes.push((
            any_aggregator,
            cgraph::Relation::Positive,
            cgraph::Strength::Strong,
        ));
    }

    let pmt_all_aggregator_info = "All Aggregator for PaymentMethodType";
    builder
        .make_all_aggregator(&agg_nodes, Some(pmt_all_aggregator_info), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)
}

#[cfg(feature = "v2")]
fn compile_payment_method_enabled(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    enabled: common_types::payment_methods::PaymentMethodsEnabled,
) -> Result<Option<cgraph::NodeId>, KgraphError> {
    let agg_id = if !enabled
        .payment_method_subtypes
        .as_ref()
        .map(|v| v.is_empty())
        .unwrap_or(true)
    {
        let pm_info = "PaymentMethod";
        let pm_id = builder.make_value_node(
            enabled
                .payment_method_type
                .into_dir_value()
                .map(Into::into)?,
            Some(pm_info),
            None::<()>,
        );

        let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

        if let Some(pm_types) = enabled.payment_method_subtypes {
            for pm_type in pm_types {
                let node_id =
                    compile_request_pm_types(builder, pm_type, enabled.payment_method_type)?;
                agg_nodes.push((
                    node_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Strong,
                ));
            }
        }

        let any_aggregator_info = "Any aggregation for PaymentMethodsType";
        let pm_type_agg_id = builder
            .make_any_aggregator(&agg_nodes, Some(any_aggregator_info), None::<()>, None)
            .map_err(KgraphError::GraphConstructionError)?;

        let all_aggregator_info = "All aggregation for PaymentMethod";
        let enabled_pm_agg_id = builder
            .make_all_aggregator(
                &[
                    (pm_id, cgraph::Relation::Positive, cgraph::Strength::Strong),
                    (
                        pm_type_agg_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                ],
                Some(all_aggregator_info),
                None::<()>,
                None,
            )
            .map_err(KgraphError::GraphConstructionError)?;

        Some(enabled_pm_agg_id)
    } else {
        None
    };

    Ok(agg_id)
}

#[cfg(feature = "v1")]
fn compile_payment_method_enabled(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    enabled: admin_api::PaymentMethodsEnabled,
) -> Result<Option<cgraph::NodeId>, KgraphError> {
    let agg_id = if !enabled
        .payment_method_types
        .as_ref()
        .map(|v| v.is_empty())
        .unwrap_or(true)
    {
        let pm_info = "PaymentMethod";
        let pm_id = builder.make_value_node(
            enabled.payment_method.into_dir_value().map(Into::into)?,
            Some(pm_info),
            None::<()>,
        );

        let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

        if let Some(pm_types) = enabled.payment_method_types {
            for pm_type in pm_types {
                let node_id = compile_request_pm_types(builder, pm_type, enabled.payment_method)?;
                agg_nodes.push((
                    node_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Strong,
                ));
            }
        }

        let any_aggregator_info = "Any aggregation for PaymentMethodsType";
        let pm_type_agg_id = builder
            .make_any_aggregator(&agg_nodes, Some(any_aggregator_info), None::<()>, None)
            .map_err(KgraphError::GraphConstructionError)?;

        let all_aggregator_info = "All aggregation for PaymentMethod";
        let enabled_pm_agg_id = builder
            .make_all_aggregator(
                &[
                    (pm_id, cgraph::Relation::Positive, cgraph::Strength::Strong),
                    (
                        pm_type_agg_id,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Strong,
                    ),
                ],
                Some(all_aggregator_info),
                None::<()>,
                None,
            )
            .map_err(KgraphError::GraphConstructionError)?;

        Some(enabled_pm_agg_id)
    } else {
        None
    };

    Ok(agg_id)
}

macro_rules! collect_global_variants {
    ($parent_enum:ident) => {
        &mut dir::enums::$parent_enum::iter()
            .map(dir::DirValue::$parent_enum)
            .collect::<Vec<_>>()
    };
}

// #[cfg(feature = "v1")]
fn global_vec_pmt(
    enabled_pmt: Vec<dir::DirValue>,
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
) -> Vec<cgraph::NodeId> {
    let mut global_vector: Vec<dir::DirValue> = Vec::new();

    global_vector.append(collect_global_variants!(PayLaterType));
    global_vector.append(collect_global_variants!(WalletType));
    global_vector.append(collect_global_variants!(BankRedirectType));
    global_vector.append(collect_global_variants!(BankDebitType));
    global_vector.append(collect_global_variants!(CryptoType));
    global_vector.append(collect_global_variants!(RewardType));
    global_vector.append(collect_global_variants!(RealTimePaymentType));
    global_vector.append(collect_global_variants!(UpiType));
    global_vector.append(collect_global_variants!(VoucherType));
    global_vector.append(collect_global_variants!(GiftCardType));
    global_vector.append(collect_global_variants!(BankTransferType));
    global_vector.append(collect_global_variants!(CardRedirectType));
    global_vector.append(collect_global_variants!(OpenBankingType));
    global_vector.append(collect_global_variants!(MobilePaymentType));
    global_vector.push(dir::DirValue::PaymentMethod(
        dir::enums::PaymentMethod::Card,
    ));

    let global_vector = global_vector
        .into_iter()
        .filter(|global_value| !enabled_pmt.contains(global_value))
        .collect::<Vec<_>>();

    global_vector
        .into_iter()
        .map(|dir_v| {
            builder.make_value_node(
                cgraph::NodeValue::Value(dir_v),
                Some("Payment Method Type"),
                None::<()>,
            )
        })
        .collect::<Vec<_>>()
}

fn compile_graph_for_countries_and_currencies(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    config: &kgraph_types::CurrencyCountryFlowFilter,
    payment_method_type_node: cgraph::NodeId,
) -> Result<cgraph::NodeId, KgraphError> {
    let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();
    agg_nodes.push((
        payment_method_type_node,
        cgraph::Relation::Positive,
        cgraph::Strength::Normal,
    ));
    if let Some(country) = config.country.clone() {
        let node_country = country
            .into_iter()
            .map(|country| dir::DirValue::BillingCountry(api_enums::Country::from_alpha2(country)))
            .collect();
        let country_agg = builder
            .make_in_aggregator(node_country, Some("Configs for Country"), None::<()>)
            .map_err(KgraphError::GraphConstructionError)?;
        agg_nodes.push((
            country_agg,
            cgraph::Relation::Positive,
            cgraph::Strength::Weak,
        ))
    }

    if let Some(currency) = config.currency.clone() {
        let node_currency = currency
            .into_iter()
            .map(IntoDirValue::into_dir_value)
            .collect::<Result<Vec<_>, _>>()?;
        let currency_agg = builder
            .make_in_aggregator(node_currency, Some("Configs for Currency"), None::<()>)
            .map_err(KgraphError::GraphConstructionError)?;
        agg_nodes.push((
            currency_agg,
            cgraph::Relation::Positive,
            cgraph::Strength::Normal,
        ))
    }
    if let Some(capture_method) = config
        .not_available_flows
        .and_then(|naf| naf.capture_method)
    {
        let make_capture_node = builder.make_value_node(
            cgraph::NodeValue::Value(dir::DirValue::CaptureMethod(capture_method)),
            Some("Configs for CaptureMethod"),
            None::<()>,
        );
        agg_nodes.push((
            make_capture_node,
            cgraph::Relation::Negative,
            cgraph::Strength::Normal,
        ))
    }

    builder
        .make_all_aggregator(
            &agg_nodes,
            Some("Country & Currency Configs With Payment Method Type"),
            None::<()>,
            None,
        )
        .map_err(KgraphError::GraphConstructionError)
}

// #[cfg(feature = "v1")]
fn compile_config_graph(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    config: &kgraph_types::CountryCurrencyFilter,
    connector: api_enums::RoutableConnectors,
) -> Result<cgraph::NodeId, KgraphError> {
    let mut agg_node_id: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();
    let mut pmt_enabled: Vec<dir::DirValue> = Vec::new();
    if let Some(pmt) = config
        .connector_configs
        .get(&connector)
        .or(config.default_configs.as_ref())
        .map(|inner| inner.0.clone())
    {
        for pm_filter_key in pmt {
            match pm_filter_key {
                (kgraph_types::PaymentMethodFilterKey::PaymentMethodType(pm), filter) => {
                    let dir_val_pm = get_dir_value_payment_method(pm)?;

                    let pm_node = if pm == api_enums::PaymentMethodType::Credit
                        || pm == api_enums::PaymentMethodType::Debit
                    {
                        pmt_enabled
                            .push(dir::DirValue::PaymentMethod(api_enums::PaymentMethod::Card));
                        builder.make_value_node(
                            cgraph::NodeValue::Value(dir::DirValue::PaymentMethod(
                                dir::enums::PaymentMethod::Card,
                            )),
                            Some("PaymentMethod"),
                            None::<()>,
                        )
                    } else {
                        pmt_enabled.push(dir_val_pm.clone());
                        builder.make_value_node(
                            cgraph::NodeValue::Value(dir_val_pm),
                            Some("PaymentMethodType"),
                            None::<()>,
                        )
                    };

                    let node_config =
                        compile_graph_for_countries_and_currencies(builder, &filter, pm_node)?;

                    agg_node_id.push((
                        node_config,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Normal,
                    ));
                }
                (kgraph_types::PaymentMethodFilterKey::CardNetwork(cn), filter) => {
                    let dir_val_cn = cn.clone().into_dir_value()?;
                    pmt_enabled.push(dir_val_cn);
                    let cn_node = builder.make_value_node(
                        cn.clone().into_dir_value().map(Into::into)?,
                        Some("CardNetwork"),
                        None::<()>,
                    );
                    let node_config =
                        compile_graph_for_countries_and_currencies(builder, &filter, cn_node)?;

                    agg_node_id.push((
                        node_config,
                        cgraph::Relation::Positive,
                        cgraph::Strength::Normal,
                    ));
                }
            }
        }
    }
    let global_vector_pmt: Vec<cgraph::NodeId> = global_vec_pmt(pmt_enabled, builder);
    let any_agg_pmt: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = global_vector_pmt
        .into_iter()
        .map(|node| (node, cgraph::Relation::Positive, cgraph::Strength::Normal))
        .collect::<Vec<_>>();
    let any_agg_node = builder
        .make_any_aggregator(
            &any_agg_pmt,
            Some("Any Aggregator For Payment Method Types"),
            None::<()>,
            None,
        )
        .map_err(KgraphError::GraphConstructionError)?;

    agg_node_id.push((
        any_agg_node,
        cgraph::Relation::Positive,
        cgraph::Strength::Normal,
    ));

    builder
        .make_any_aggregator(&agg_node_id, Some("Configs"), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)
}

#[cfg(feature = "v2")]
fn compile_merchant_connector_graph(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    mca: admin_api::MerchantConnectorResponse,


pub struct WorldlineRefundRequest {
    amount_of_money: AmountOfMoney,
}


pub async fn update_v1_and_v2_user_roles_in_db(
    state: &SessionState,
    user_id: &str,
    tenant_id: &id_type::TenantId,
    org_id: &id_type::OrganizationId,
    merchant_id: Option<&id_type::MerchantId>,
    profile_id: Option<&id_type::ProfileId>,
    update: UserRoleUpdate,
) -> (
    Result<UserRole, Report<StorageError>>,
    Result<UserRole, Report<StorageError>>,
) {
    let updated_v1_role = state
        .global_store
        .update_user_role_by_user_id_and_lineage(
            user_id,
            tenant_id,
            org_id,
            merchant_id,
            profile_id,
            update.clone(),
            UserRoleVersion::V1,
        )
        .await
        .map_err(|e| {
            logger::error!("Error updating user_role {e:?}");
            e
        });

    let updated_v2_role = state
        .global_store
        .update_user_role_by_user_id_and_lineage(
            user_id,
            tenant_id,
            org_id,
            merchant_id,
            profile_id,
            update,
            UserRoleVersion::V2,
        )
        .await
        .map_err(|e| {
            logger::error!("Error updating user_role {e:?}");
            e
        });

    (updated_v1_role, updated_v2_role)
}


pub struct EbanxRouterData<T> {
    pub amount: FloatMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
    pub router_data: T,
}


pub struct SdkPaymentsSessionUpdateData {
    pub order_tax_amount: MinorUnit,
    // amount here would include amount, surcharge_amount, order_tax_amount and shipping_cost
    pub amount: MinorUnit,
    /// original amount sent by the merchant
    pub order_amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub session_id: Option<String>,
    pub shipping_cost: Option<MinorUnit>,
}


impl Responder {
    let flow = Flow::PayoutLinkInitiate;
    let (merchant_id, payout_id) = path.into_inner();
    let payload = PayoutLinkInitiateRequest {
        merchant_id: merchant_id.clone(),
        payout_id,
    };
    let headers = req.headers();
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload.clone(),
        |state, auth, req, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            initiate_payout_link(state, merchant_context, req, headers)
        },
        &auth::MerchantIdAuth(merchant_id),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub trait ApiEventMetric<T>
where
    T: AnalyticsDataSource + ApiEventMetricAnalytics,
{
    async fn load_metrics(
        &self,
        dimensions: &[ApiEventDimensions],
        merchant_id: &common_utils::id_type::MerchantId,
        filters: &ApiEventFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(ApiEventMetricsBucketIdentifier, ApiEventMetricRow)>>;
}


pub struct ClientProcessorInformation {
    network_transaction_id: Option<String>,
    avs: Option<Avs>,
    card_verification: Option<CardVerification>,
    merchant_advice: Option<MerchantAdvice>,
    response_code: Option<String>,
}


impl Responder {
    let flow = Flow::PaymentsSessionToken;
    let payload = json_payload.into_inner();

    let header_payload = match HeaderPayload::foreign_try_from(req.headers()) {
        Ok(headers) => headers,
        Err(error) => {
            logger::error!(
                ?error,
                "Failed to get headers in payments_connector_session"
            );
            HeaderPayload::default()
        }
    };

    tracing::Span::current().record("payment_id", payload.payment_id.get_string_repr());

    let locking_action = payload.get_locking_input(flow.clone());

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth: auth::AuthenticationData, payload, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_core::<
                api_types::Session,
                payment_types::PaymentsSessionResponse,
                _,
                _,
                _,
                payments::PaymentData<api_types::Session>,
            >(
                state,
                req_state,
                merchant_context,
                auth.profile_id,
                payments::PaymentSession,
                payload,
                api::AuthFlow::Client,
                payments::CallConnectorAction::Trigger,
                None,
                header_payload.clone(),
            )
        },
        &auth::HeaderAuth(auth::PublishableKeyAuth),
        locking_action,
    ))
    .await
}


pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Relay> {
        generics::generic_insert(conn, self).await
    }


pub fn read(db_table: &Value) -> Result<Self, toml::de::Error> {
        db_table.clone().try_into()
    }


pub fn get_tax_processor_config(
        connector: TaxConnectors,
    ) -> Result<Option<ConnectorTomlConfig>, String> {
        let connector_data = Self::new()?;
        match connector {
            TaxConnectors::Taxjar => Ok(connector_data.taxjar),
        }
    }


pub fn get_jwt_from_authorization_header(headers: &HeaderMap) -> RouterResult<&str> {
    headers
        .get(headers::AUTHORIZATION)
        .get_required_value(headers::AUTHORIZATION)?
        .to_str()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to convert JWT token to string")?
        .strip_prefix("Bearer ")
        .ok_or(errors::ApiErrorResponse::InvalidJwtToken.into())
}


pub struct ShoppingCart {
    pub items: Vec<Item>,
}


impl api::PaymentAuthorize for Nomupay {}

impl api::PaymentAuthorize for for Nomupay


impl ApiErrorResponse {
    pub(crate) fn get_internal_error(&self) -> &ApiError {
        match self {
            Self::Unauthorized(i)
            | Self::ForbiddenCommonResource(i)
            | Self::ForbiddenPrivateResource(i)
            | Self::Conflict(i)
            | Self::Gone(i)
            | Self::Unprocessable(i)
            | Self::InternalServerError(i)
            | Self::NotImplemented(i)
            | Self::NotFound(i)
            | Self::MethodNotAllowed(i)
            | Self::BadRequest(i)
            | Self::DomainError(i)
            | Self::ConnectorError(i, _) => i,
        }
    }

    pub fn get_internal_error_mut(&mut self) -> &mut ApiError {
        match self {
            Self::Unauthorized(i)
            | Self::ForbiddenCommonResource(i)
            | Self::ForbiddenPrivateResource(i)
            | Self::Conflict(i)
            | Self::Gone(i)
            | Self::Unprocessable(i)
            | Self::InternalServerError(i)
            | Self::NotImplemented(i)
            | Self::NotFound(i)
            | Self::MethodNotAllowed(i)
            | Self::BadRequest(i)
            | Self::DomainError(i)
            | Self::ConnectorError(i, _) => i,
        }
    }

    pub(crate) fn error_type(&self) -> &'static str {
        match self {
            Self::Unauthorized(_)
            | Self::ForbiddenCommonResource(_)
            | Self::ForbiddenPrivateResource(_)
            | Self::Conflict(_)
            | Self::Gone(_)
            | Self::Unprocessable(_)
            | Self::NotImplemented(_)
            | Self::MethodNotAllowed(_)
            | Self::NotFound(_)
            | Self::BadRequest(_) => "invalid_request",
            Self::InternalServerError(_) => "api",
            Self::DomainError(_) => "blocked",
            Self::ConnectorError(_, _) => "connector",
        }
    }
}


impl api::Payment for Billwerk {}


pub struct RoutingEventsWrapper<Req>
where
    Req: Serialize + Clone,
{
    pub tenant_id: id_type::TenantId,
    pub request_id: Option<RequestId>,
    pub payment_id: String,
    pub profile_id: id_type::ProfileId,
    pub merchant_id: id_type::MerchantId,
    pub flow: String,
    pub request: Option<Req>,
    pub parse_response: bool,
    pub log_event: bool,
    pub routing_event: Option<routing_events::RoutingEvent>,
}


pub fn new(to_factor: Decimal, from_factor: Decimal) -> Self {
        Self {
            to_factor,
            from_factor,
        }
    }


pub fn get_enable_payment_response_hash(&self) -> bool {
        self.enable_payment_response_hash.unwrap_or(true)
    }


pub struct DashboardMetadataNew {
    pub user_id: Option<String>,
    pub merchant_id: id_type::MerchantId,
    pub org_id: id_type::OrganizationId,
    pub data_key: enums::DashboardMetadata,
    pub data_value: Secret<serde_json::Value>,
    pub created_by: String,
    pub created_at: PrimitiveDateTime,
    pub last_modified_by: String,
    pub last_modified_at: PrimitiveDateTime,
}


pub trait RefundDistributionAnalytics: LoadRow<RefundDistributionRow> {}


impl api::PaymentToken for Fiserv {}


File: crates/scheduler/src/consumer/workflows.rs

use async_trait::async_trait;
use common_utils::errors::CustomResult;
pub use diesel_models::process_tracker as storage;
use diesel_models::process_tracker::business_status;
use router_env::logger;

use crate::{errors, SchedulerSessionState};

pub type WorkflowSelectorFn =
    fn(&storage::ProcessTracker) -> Result<(), errors::ProcessTrackerError>;

#[async_trait]
pub trait ProcessTrackerWorkflows<T>: Send + Sync {
    // The core execution of the workflow
    async fn trigger_workflow<'a>(
        &'a self,
        _state: &'a T,
        _process: storage::ProcessTracker,
    ) -> CustomResult<(), errors::ProcessTrackerError> {
        Err(errors::ProcessTrackerError::NotImplemented)?
    }

    async fn execute_workflow<'a>(
        &'a self,
        operation: Box<dyn ProcessTrackerWorkflow<T>>,
        state: &'a T,
        process: storage::ProcessTracker,
    ) -> CustomResult<(), errors::ProcessTrackerError>
    where
        T: SchedulerSessionState,
    {
        let app_state = &state.clone();
        let output = operation.execute_workflow(app_state, process.clone()).await;
        match output {
            Ok(_) => operation.success_handler(app_state, process).await,
            Err(error) => match operation
                .error_handler(app_state, process.clone(), error)
                .await
            {
                Ok(_) => (),
                Err(error) => {
                    logger::error!(
                        ?error,
                        "Failed to handle process tracker workflow execution error"
                    );
                    let status = app_state
                        .get_db()
                        .as_scheduler()
                        .finish_process_with_business_status(
                            process,
                            business_status::GLOBAL_FAILURE,
                        )
                        .await;
                    if let Err(error) = status {
                        logger::error!(?error, "Failed to update process business status");
                    }
                }
            },
        };
        Ok(())
    }
}

#[async_trait]
pub trait ProcessTrackerWorkflow<T>: Send + Sync {
    /// The core execution of the workflow
    async fn execute_workflow<'a>(
        &'a self,
        _state: &'a T,
        _process: storage::ProcessTracker,
    ) -> Result<(), errors::ProcessTrackerError> {
        Err(errors::ProcessTrackerError::NotImplemented)?
    }

    /// Callback function after successful execution of the `execute_workflow`
    async fn success_handler<'a>(&'a self, _state: &'a T, _process: storage::ProcessTracker) {}

    /// Callback function after error received from `execute_workflow`
    async fn error_handler<'a>(
        &'a self,
        _state: &'a T,
        _process: storage::ProcessTracker,
        _error: errors::ProcessTrackerError,
    ) -> CustomResult<(), errors::ProcessTrackerError> {
        Err(errors::ProcessTrackerError::NotImplemented)?
    }
}