        self,
        state: &SessionState,
        _merchant_id: &id_type::MerchantId,
        key_store: &domain::MerchantKeyStore,
    ) -> RouterResult<storage::MerchantAccountUpdate> {
        let key_manager_state = &state.into();
        let key = key_store.key.get_inner().peek();

        let merchant_details = self.get_merchant_details_as_secret().change_context(
            errors::ApiErrorResponse::InvalidDataValue {
                field_name: "merchant_details",
            },
        )?;

        let metadata = self.get_metadata_as_secret().change_context(
            errors::ApiErrorResponse::InvalidDataValue {
                field_name: "metadata",
            },
        )?;

        let identifier = km_types::Identifier::Merchant(key_store.merchant_id.clone());
        Ok(storage::MerchantAccountUpdate::Update {
            merchant_name: self
                .merchant_name
                .map(Secret::new)
                .async_lift(|inner| async {
                    domain_types::crypto_operation(
                        key_manager_state,
                        type_name!(storage::MerchantAccount),
                        domain_types::CryptoOperation::EncryptOptional(inner),
                        identifier.clone(),
                        key,
                    )
                    .await
                    .and_then(|val| val.try_into_optionaloperation())
                })
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Unable to encrypt merchant name")?,
            merchant_details: merchant_details
                .async_lift(|inner| async {
                    domain_types::crypto_operation(
                        key_manager_state,
                        type_name!(storage::MerchantAccount),
                        domain_types::CryptoOperation::EncryptOptional(inner),
                        identifier.clone(),
                        key,
                    )
                    .await
                    .and_then(|val| val.try_into_optionaloperation())
                })
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Unable to encrypt merchant details")?,
            metadata: metadata.map(Box::new),
            publishable_key: None,
        })
    }
}

pub async fn merchant_account_update(
    state: SessionState,
    merchant_id: &id_type::MerchantId,
    _profile_id: Option<id_type::ProfileId>,
    req: api::MerchantAccountUpdate,
) -> RouterResponse<api::MerchantAccountResponse> {
    let db = state.store.as_ref();
    let key_manager_state = &(&state).into();
    let key_store = db
        .get_merchant_key_store_by_merchant_id(
            key_manager_state,
            merchant_id,
            &db.get_master_key().to_vec().into(),
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

    let merchant_account_storage_object = req
        .get_update_merchant_object(&state, merchant_id, &key_store)
        .await
        .attach_printable("Failed to create merchant account update object")?;

    let response = db
        .update_specific_fields_in_merchant(
            key_manager_state,
            merchant_id,
            merchant_account_storage_object,
            &key_store,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

    Ok(service_api::ApplicationResponse::Json(
        api::MerchantAccountResponse::foreign_try_from(response)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed while generating response")?,
    ))
}

pub async fn merchant_account_delete(
    state: SessionState,
    merchant_id: id_type::MerchantId,
) -> RouterResponse<api::MerchantAccountDeleteResponse> {
    let mut is_deleted = false;
    let db = state.store.as_ref();
    let key_manager_state = &(&state).into();
    let merchant_key_store = db
        .get_merchant_key_store_by_merchant_id(
            key_manager_state,
            &merchant_id,
            &state.store.get_master_key().to_vec().into(),
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

    let merchant_account = db
        .find_merchant_account_by_merchant_id(key_manager_state, &merchant_id, &merchant_key_store)
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

    let is_merchant_account_deleted = db
        .delete_merchant_account_by_merchant_id(&merchant_id)
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
    if is_merchant_account_deleted {
        let is_merchant_key_store_deleted = db
            .delete_merchant_key_store_by_merchant_id(&merchant_id)
            .await
            .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
        is_deleted = is_merchant_account_deleted && is_merchant_key_store_deleted;
    }

    let state = state.clone();
    authentication::decision::spawn_tracked_job(
        async move {
            authentication::decision::revoke_api_key(
                &state,
                merchant_account.publishable_key.into(),
            )
            .await
        },
        authentication::decision::REVOKE,
    );

    match db
        .delete_config_by_key(merchant_id.get_requires_cvv_key().as_str())
        .await
    {
        Ok(_) => Ok::<_, errors::ApiErrorResponse>(()),
        Err(err) => {
            if err.current_context().is_db_not_found() {
                logger::error!("requires_cvv config not found in db: {err:?}");
                Ok(())
            } else {
                Err(err
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed while deleting requires_cvv config"))?
            }
        }
    }
    .ok();

    let response = api::MerchantAccountDeleteResponse {
        merchant_id,
        deleted: is_deleted,
    };
    Ok(service_api::ApplicationResponse::Json(response))
}

#[cfg(feature = "v1")]
async fn get_parent_merchant(
    state: &SessionState,
    sub_merchants_enabled: Option<bool>,
    parent_merchant: Option<&id_type::MerchantId>,
    key_store: &domain::MerchantKeyStore,
) -> RouterResult<Option<id_type::MerchantId>> {
    Ok(match sub_merchants_enabled {
        Some(true) => {
            Some(
                parent_merchant.ok_or_else(|| {
                    report!(errors::ValidationError::MissingRequiredField {
                        field_name: "parent_merchant_id".to_string()
                    })
                    .change_context(errors::ApiErrorResponse::PreconditionFailed {
                        message: "If `sub_merchants_enabled` is `true`, then `parent_merchant_id` is mandatory".to_string(),
                    })
                })
                .map(|id| validate_merchant_id(state, id,key_store).change_context(
                    errors::ApiErrorResponse::InvalidDataValue { field_name: "parent_merchant_id" }
                ))?
                .await?
                .get_id().to_owned()
            )
        }
        _ => None,
    })
}

#[cfg(feature = "v1")]
async fn validate_merchant_id(
    state: &SessionState,
    merchant_id: &id_type::MerchantId,
    key_store: &domain::MerchantKeyStore,
) -> RouterResult<domain::MerchantAccount> {
    let db = &*state.store;
    db.find_merchant_account_by_merchant_id(&state.into(), merchant_id, key_store)
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
}

struct ConnectorStatusAndDisabledValidation<'a> {
    status: &'a Option<api_enums::ConnectorStatus>,
    disabled: &'a Option<bool>,
    auth: &'a types::ConnectorAuthType,
    current_status: &'a api_enums::ConnectorStatus,
}

impl ConnectorStatusAndDisabledValidation<'_> {
    fn validate_status_and_disabled(
        &self,
    ) -> RouterResult<(api_enums::ConnectorStatus, Option<bool>)> {
        let connector_status = match (self.status, self.auth) {
            (
                Some(common_enums::ConnectorStatus::Active),
                types::ConnectorAuthType::TemporaryAuth,
            ) => {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Connector status cannot be active when using TemporaryAuth"
                        .to_string(),
                }
                .into());
            }
            (Some(status), _) => status,
            (None, types::ConnectorAuthType::TemporaryAuth) => {
                &common_enums::ConnectorStatus::Inactive
            }
            (None, _) => self.current_status,
        };

        let disabled = match (self.disabled, connector_status) {
            (Some(false), common_enums::ConnectorStatus::Inactive) => {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Connector cannot be enabled when connector_status is inactive or when using TemporaryAuth"
                        .to_string(),
                }
                .into());
            }
            (Some(disabled), _) => Some(*disabled),
            (None, common_enums::ConnectorStatus::Inactive) => Some(true),
            // Enable the connector if nothing is passed in the request
            (None, _) => Some(false),
        };

        Ok((*connector_status, disabled))
    }
}

struct ConnectorMetadata<'a> {
    connector_metadata: &'a Option<pii::SecretSerdeValue>,
}

impl ConnectorMetadata<'_> {
    fn validate_apple_pay_certificates_in_mca_metadata(&self) -> RouterResult<()> {
        self.connector_metadata
            .clone()
            .map(api_models::payments::ConnectorMetadata::from_value)
            .transpose()
            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
                field_name: "metadata".to_string(),
                expected_format: "connector metadata".to_string(),
            })?
            .and_then(|metadata| metadata.get_apple_pay_certificates())
            .map(|(certificate, certificate_key)| {
                client::create_identity_from_certificate_and_key(certificate, certificate_key)
            })
            .transpose()
            .change_context(errors::ApiErrorResponse::InvalidDataValue {
                field_name: "certificate/certificate key",
            })?;
        Ok(())
    }
}

struct PMAuthConfigValidation<'a> {
    connector_type: &'a api_enums::ConnectorType,
    pm_auth_config: &'a Option<pii::SecretSerdeValue>,
    db: &'a dyn StorageInterface,
    merchant_id: &'a id_type::MerchantId,
    profile_id: &'a id_type::ProfileId,
    key_store: &'a domain::MerchantKeyStore,
    key_manager_state: &'a KeyManagerState,
}

impl PMAuthConfigValidation<'_> {
    async fn validate_pm_auth(&self, val: &pii::SecretSerdeValue) -> RouterResponse<()> {
        let config = serde_json::from_value::<api_models::pm_auth::PaymentMethodAuthConfig>(
            val.clone().expose(),
        )
        .change_context(errors::ApiErrorResponse::InvalidRequestData {
            message: "invalid data received for payment method auth config".to_string(),
        })
        .attach_printable("Failed to deserialize Payment Method Auth config")?;

        let all_mcas = self
            .db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                self.key_manager_state,
                self.merchant_id,
                true,
                self.key_store,
            )
            .await
            .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: self.merchant_id.get_string_repr().to_owned(),
            })?;
        for conn_choice in config.enabled_payment_methods {
            let pm_auth_mca = all_mcas
                .iter()
                .find(|mca| mca.get_id() == conn_choice.mca_id)
                .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "payment method auth connector account not found".to_string(),
                })?;

            if &pm_auth_mca.profile_id != self.profile_id {
                return Err(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "payment method auth profile_id differs from connector profile_id"
                        .to_string(),
                }
                .into());
            }
        }

        Ok(services::ApplicationResponse::StatusOk)
    }

    async fn validate_pm_auth_config(&self) -> RouterResult<()> {
        if self.connector_type != &api_enums::ConnectorType::PaymentMethodAuth {
            if let Some(val) = self.pm_auth_config.clone() {
                self.validate_pm_auth(&val).await?;
            }
        }
        Ok(())
    }
}

struct ConnectorTypeAndConnectorName<'a> {
    connector_type: &'a api_enums::ConnectorType,
    connector_name: &'a api_enums::Connector,
}

impl ConnectorTypeAndConnectorName<'_> {
    fn get_routable_connector(&self) -> RouterResult<Option<api_enums::RoutableConnectors>> {
        let mut routable_connector =
            api_enums::RoutableConnectors::from_str(&self.connector_name.to_string()).ok();

        let vault_connector =
            api_enums::convert_vault_connector(self.connector_name.to_string().as_str());
        let pm_auth_connector =
            api_enums::convert_pm_auth_connector(self.connector_name.to_string().as_str());
        let authentication_connector =
            api_enums::convert_authentication_connector(self.connector_name.to_string().as_str());
        let tax_connector =
            api_enums::convert_tax_connector(self.connector_name.to_string().as_str());
        let billing_connector =
            api_enums::convert_billing_connector(self.connector_name.to_string().as_str());

        if pm_auth_connector.is_some() {
            if self.connector_type != &api_enums::ConnectorType::PaymentMethodAuth
                && self.connector_type != &api_enums::ConnectorType::PaymentProcessor
            {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector type given".to_string(),
                }
                .into());
            }
        } else if authentication_connector.is_some() {
            if self.connector_type != &api_enums::ConnectorType::AuthenticationProcessor {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector type given".to_string(),
                }
                .into());
            }
        } else if tax_connector.is_some() {
            if self.connector_type != &api_enums::ConnectorType::TaxProcessor {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector type given".to_string(),
                }
                .into());
            }
        } else if billing_connector.is_some() {
            if self.connector_type != &api_enums::ConnectorType::BillingProcessor {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector type given".to_string(),
                }
                .into());
            }
        } else if vault_connector.is_some() {
            if self.connector_type != &api_enums::ConnectorType::VaultProcessor {
                return Err(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector type given".to_string(),
                }
                .into());
            }
        } else {
            let routable_connector_option = self
                .connector_name
                .to_string()
                .parse::<api_enums::RoutableConnectors>()
                .change_context(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid connector name given".to_string(),
                })?;
            routable_connector = Some(routable_connector_option);
        };
        Ok(routable_connector)
    }
}
#[cfg(feature = "v1")]
struct MerchantDefaultConfigUpdate<'a> {
    routable_connector: &'a Option<api_enums::RoutableConnectors>,
    merchant_connector_id: &'a id_type::MerchantConnectorAccountId,
    store: &'a dyn StorageInterface,
    merchant_id: &'a id_type::MerchantId,
    profile_id: &'a id_type::ProfileId,
    transaction_type: &'a api_enums::TransactionType,
}
#[cfg(feature = "v1")]
impl MerchantDefaultConfigUpdate<'_> {
    async fn retrieve_and_update_default_fallback_routing_algorithm_if_routable_connector_exists(
        &self,
    ) -> RouterResult<()> {
        let mut default_routing_config = routing::helpers::get_merchant_default_config(
            self.store,
            self.merchant_id.get_string_repr(),
            self.transaction_type,
        )
        .await?;

        let mut default_routing_config_for_profile = routing::helpers::get_merchant_default_config(
            self.store,
            self.profile_id.get_string_repr(),
            self.transaction_type,
        )
        .await?;

        if let Some(routable_connector_val) = self.routable_connector {
            let choice = routing_types::RoutableConnectorChoice {
                choice_kind: routing_types::RoutableChoiceKind::FullStruct,
                connector: *routable_connector_val,
                merchant_connector_id: Some(self.merchant_connector_id.clone()),
            };
            if !default_routing_config.contains(&choice) {
                default_routing_config.push(choice.clone());
                routing::helpers::update_merchant_default_config(
                    self.store,
                    self.merchant_id.get_string_repr(),
                    default_routing_config.clone(),
                    self.transaction_type,
                )
                .await?;
            }
            if !default_routing_config_for_profile.contains(&choice.clone()) {
                default_routing_config_for_profile.push(choice);
                routing::helpers::update_merchant_default_config(
                    self.store,
                    self.profile_id.get_string_repr(),
                    default_routing_config_for_profile.clone(),
                    self.transaction_type,
                )
                .await?;
            }
        }
        Ok(())
    }

    async fn retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists(
        &self,
    ) -> RouterResult<()> {
        let mut default_routing_config = routing::helpers::get_merchant_default_config(
            self.store,
            self.merchant_id.get_string_repr(),
            self.transaction_type,
        )
        .await?;

        let mut default_routing_config_for_profile = routing::helpers::get_merchant_default_config(
            self.store,
            self.profile_id.get_string_repr(),
            self.transaction_type,
        )
        .await?;

        if let Some(routable_connector_val) = self.routable_connector {
            let choice = routing_types::RoutableConnectorChoice {
                choice_kind: routing_types::RoutableChoiceKind::FullStruct,
                connector: *routable_connector_val,
                merchant_connector_id: Some(self.merchant_connector_id.clone()),
            };
            if default_routing_config.contains(&choice) {
                default_routing_config.retain(|mca| {
                    mca.merchant_connector_id.as_ref() != Some(self.merchant_connector_id)
                });
                routing::helpers::update_merchant_default_config(
                    self.store,
                    self.merchant_id.get_string_repr(),
                    default_routing_config.clone(),
                    self.transaction_type,
                )
                .await?;
            }
            if default_routing_config_for_profile.contains(&choice.clone()) {
                default_routing_config_for_profile.retain(|mca| {
                    mca.merchant_connector_id.as_ref() != Some(self.merchant_connector_id)
                });
                routing::helpers::update_merchant_default_config(
                    self.store,
                    self.profile_id.get_string_repr(),
                    default_routing_config_for_profile.clone(),
                    self.transaction_type,
                )
                .await?;
            }
        }
        Ok(())
    }
}
#[cfg(feature = "v2")]
struct DefaultFallbackRoutingConfigUpdate<'a> {
    routable_connector: &'a Option<api_enums::RoutableConnectors>,
    merchant_connector_id: &'a id_type::MerchantConnectorAccountId,
    store: &'a dyn StorageInterface,
    business_profile: domain::Profile,
    key_store: hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
    key_manager_state: &'a KeyManagerState,
}
#[cfg(feature = "v2")]
impl DefaultFallbackRoutingConfigUpdate<'_> {
    async fn retrieve_and_update_default_fallback_routing_algorithm_if_routable_connector_exists(
        &self,
    ) -> RouterResult<()> {
        let profile_wrapper = ProfileWrapper::new(self.business_profile.clone());
        let default_routing_config_for_profile =
            &mut profile_wrapper.get_default_fallback_list_of_connector_under_profile()?;
        if let Some(routable_connector_val) = self.routable_connector {
            let choice = routing_types::RoutableConnectorChoice {
                choice_kind: routing_types::RoutableChoiceKind::FullStruct,
                connector: *routable_connector_val,
                merchant_connector_id: Some(self.merchant_connector_id.clone()),
            };
            if !default_routing_config_for_profile.contains(&choice.clone()) {
                default_routing_config_for_profile.push(choice);

                profile_wrapper
                    .update_default_fallback_routing_of_connectors_under_profile(
                        self.store,
                        default_routing_config_for_profile,
                        self.key_manager_state,
                        &self.key_store,
                    )
                    .await?
            }
        }
        Ok(())
    }

    async fn retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists(
        &self,
    ) -> RouterResult<()> {
        let profile_wrapper = ProfileWrapper::new(self.business_profile.clone());
        let default_routing_config_for_profile =
            &mut profile_wrapper.get_default_fallback_list_of_connector_under_profile()?;
        if let Some(routable_connector_val) = self.routable_connector {
            let choice = routing_types::RoutableConnectorChoice {
                choice_kind: routing_types::RoutableChoiceKind::FullStruct,
                connector: *routable_connector_val,
                merchant_connector_id: Some(self.merchant_connector_id.clone()),
            };
            if default_routing_config_for_profile.contains(&choice.clone()) {
                default_routing_config_for_profile.retain(|mca| {
                    mca.merchant_connector_id.as_ref() != Some(self.merchant_connector_id)
                });

                profile_wrapper
                    .update_default_fallback_routing_of_connectors_under_profile(
                        self.store,
                        default_routing_config_for_profile,
                        self.key_manager_state,
                        &self.key_store,
                    )
                    .await?
            }
        }
        Ok(())
    }
}
#[cfg(any(feature = "v1", feature = "v2", feature = "olap"))]
#[async_trait::async_trait]
trait MerchantConnectorAccountUpdateBridge {
    async fn get_merchant_connector_account_from_id(
        self,
        db: &dyn StorageInterface,
        merchant_id: &id_type::MerchantId,
        merchant_connector_id: &id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::MerchantConnectorAccount>;

    async fn create_domain_model_from_request(
        self,
        state: &SessionState,
        mca: &domain::MerchantConnectorAccount,
        key_manager_state: &KeyManagerState,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<domain::MerchantConnectorAccountUpdate>;
}

#[cfg(all(feature = "v2", feature = "olap"))]
#[async_trait::async_trait]
impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnectorUpdate {
    async fn get_merchant_connector_account_from_id(
        self,
        db: &dyn StorageInterface,
        _merchant_id: &id_type::MerchantId,
        merchant_connector_id: &id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::MerchantConnectorAccount> {
        db.find_merchant_connector_account_by_id(
            key_manager_state,
            merchant_connector_id,
            key_store,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
    }

    async fn create_domain_model_from_request(
        self,
        state: &SessionState,
        mca: &domain::MerchantConnectorAccount,
        key_manager_state: &KeyManagerState,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<domain::MerchantConnectorAccountUpdate> {
        let frm_configs = self.get_frm_config_as_secret();

        let payment_methods_enabled = self.payment_methods_enabled;

        let auth = types::ConnectorAuthType::from_secret_value(
            self.connector_account_details
                .clone()
                .unwrap_or(mca.connector_account_details.clone().into_inner()),
        )
        .change_context(errors::ApiErrorResponse::InvalidDataFormat {
            field_name: "connector_account_details".to_string(),
            expected_format: "auth_type and api_key".to_string(),
        })?;

        let metadata = self.metadata.clone().or(mca.metadata.clone());

        let connector_auth_type_and_metadata_validation = ConnectorAuthTypeAndMetadataValidation {
            connector_name: &mca.connector_name,
            auth_type: &auth,
            connector_meta_data: &metadata,
        };

        connector_auth_type_and_metadata_validation.validate_auth_and_metadata_type()?;
        let connector_status_and_disabled_validation = ConnectorStatusAndDisabledValidation {
            status: &self.status,
            disabled: &self.disabled,
            auth: &auth,
            current_status: &mca.status,
        };

        let (connector_status, disabled) =
            connector_status_and_disabled_validation.validate_status_and_disabled()?;

        let pm_auth_config_validation = PMAuthConfigValidation {
            connector_type: &self.connector_type,
            pm_auth_config: &self.pm_auth_config,
            db: state.store.as_ref(),
            merchant_id: merchant_context.get_merchant_account().get_id(),
            profile_id: &mca.profile_id.clone(),
            key_store: merchant_context.get_merchant_key_store(),
            key_manager_state,
        };

        pm_auth_config_validation.validate_pm_auth_config().await?;

        let merchant_recipient_data = if let Some(data) = &self.additional_merchant_data {
            Some(
                process_open_banking_connectors(
                    state,
                    merchant_context.get_merchant_account().get_id(),
                    &auth,
                    &self.connector_type,
                    &mca.connector_name,
                    types::AdditionalMerchantData::foreign_from(data.clone()),
                    merchant_context.get_merchant_key_store(),
                )
                .await?,
            )
        } else {
            None
        }
        .map(|data| {
            serde_json::to_value(types::AdditionalMerchantData::OpenBankingRecipientData(
                data,
            ))
        })
        .transpose()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to serialize MerchantRecipientData")?;

        let encrypted_data = domain_types::crypto_operation(
            key_manager_state,
            type_name!(domain::MerchantConnectorAccount),
            domain_types::CryptoOperation::BatchEncrypt(
                UpdateEncryptableMerchantConnectorAccount::to_encryptable(
                    UpdateEncryptableMerchantConnectorAccount {
                        connector_account_details: self.connector_account_details,
                        connector_wallets_details:
                            helpers::get_connector_wallets_details_with_apple_pay_certificates(
                                &self.metadata,
                                &self.connector_wallets_details,
                            )
                            .await?,
                        additional_merchant_data: merchant_recipient_data.map(Secret::new),
                    },
                ),
            ),
            km_types::Identifier::Merchant(
                merchant_context
                    .get_merchant_key_store()
                    .merchant_id
                    .clone(),
            ),
            merchant_context.get_merchant_key_store().key.peek(),
        )
        .await
        .and_then(|val| val.try_into_batchoperation())
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed while decrypting connector account details".to_string())?;

        let encrypted_data =
            UpdateEncryptableMerchantConnectorAccount::from_encryptable(encrypted_data)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed while decrypting connector account details")?;

        let feature_metadata = self
            .feature_metadata
            .as_ref()
            .map(ForeignTryFrom::foreign_try_from)
            .transpose()?;

        Ok(storage::MerchantConnectorAccountUpdate::Update {
            connector_type: Some(self.connector_type),
            connector_label: self.connector_label.clone(),
            connector_account_details: Box::new(encrypted_data.connector_account_details),
            disabled,
            payment_methods_enabled,
            metadata: self.metadata,
            frm_configs,
            connector_webhook_details: match &self.connector_webhook_details {
                Some(connector_webhook_details) => Box::new(
                    connector_webhook_details
                        .encode_to_value()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .map(Some)?
                        .map(Secret::new),
                ),
                None => Box::new(None),
            },
            applepay_verified_domains: None,
            pm_auth_config: Box::new(self.pm_auth_config),
            status: Some(connector_status),
            additional_merchant_data: Box::new(encrypted_data.additional_merchant_data),
            connector_wallets_details: Box::new(encrypted_data.connector_wallets_details),
            feature_metadata: Box::new(feature_metadata),
        })
    }
}

#[cfg(all(feature = "v1", feature = "olap"))]
#[async_trait::async_trait]
impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnectorUpdate {
    async fn get_merchant_connector_account_from_id(
        self,
        db: &dyn StorageInterface,
        merchant_id: &id_type::MerchantId,
        merchant_connector_id: &id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::MerchantConnectorAccount> {
        db.find_by_merchant_connector_account_merchant_id_merchant_connector_id(
            key_manager_state,
            merchant_id,
            merchant_connector_id,
            key_store,
        )
        .await
        .to_not_found_response(
            errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: merchant_connector_id.get_string_repr().to_string(),
            },
        )
    }

    async fn create_domain_model_from_request(
        self,
        state: &SessionState,
        mca: &domain::MerchantConnectorAccount,
        key_manager_state: &KeyManagerState,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<domain::MerchantConnectorAccountUpdate> {
        let payment_methods_enabled = self.payment_methods_enabled.map(|pm_enabled| {
            pm_enabled
                .iter()
                .flat_map(Encode::encode_to_value)
                .map(Secret::new)
                .collect::<Vec<pii::SecretSerdeValue>>()
        });

        let frm_configs = get_frm_config_as_secret(self.frm_configs);

        let auth: types::ConnectorAuthType = self
            .connector_account_details
            .clone()
            .unwrap_or(mca.connector_account_details.clone().into_inner())
            .parse_value("ConnectorAuthType")
            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
                field_name: "connector_account_details".to_string(),
                expected_format: "auth_type and api_key".to_string(),
            })?;
        let metadata = self.metadata.clone().or(mca.metadata.clone());

        let connector_name = mca.connector_name.as_ref();
        let connector_enum = api_models::enums::Connector::from_str(connector_name)
            .change_context(errors::ApiErrorResponse::InvalidDataValue {
                field_name: "connector",
            })
            .attach_printable_lazy(|| {
                format!("unable to parse connector name {connector_name:?}")
            })?;
        let connector_auth_type_and_metadata_validation = ConnectorAuthTypeAndMetadataValidation {
            connector_name: &connector_enum,
            auth_type: &auth,
            connector_meta_data: &metadata,
        };
        connector_auth_type_and_metadata_validation.validate_auth_and_metadata_type()?;
        let connector_status_and_disabled_validation = ConnectorStatusAndDisabledValidation {
            status: &self.status,
            disabled: &self.disabled,
            auth: &auth,
            current_status: &mca.status,
        };
        let (connector_status, disabled) =
            connector_status_and_disabled_validation.validate_status_and_disabled()?;

        if self.connector_type != api_enums::ConnectorType::PaymentMethodAuth {
            if let Some(val) = self.pm_auth_config.clone() {
                validate_pm_auth(
                    val,
                    state,
                    merchant_context.get_merchant_account().get_id(),
                    merchant_context.clone(),
                    &mca.profile_id,
                )
                .await?;
            }
        }

        let merchant_recipient_data = if let Some(data) = &self.additional_merchant_data {
            Some(
                process_open_banking_connectors(
                    state,
                    merchant_context.get_merchant_account().get_id(),
                    &auth,
                    &self.connector_type,
                    &connector_enum,
                    types::AdditionalMerchantData::foreign_from(data.clone()),
                    merchant_context.get_merchant_key_store(),
                )
                .await?,
            )
        } else {
            None
        }
        .map(|data| {
            serde_json::to_value(types::AdditionalMerchantData::OpenBankingRecipientData(
                data,
            ))
        })
        .transpose()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to serialize MerchantRecipientData")?;

        let encrypted_data = domain_types::crypto_operation(
            key_manager_state,
            type_name!(domain::MerchantConnectorAccount),
            domain_types::CryptoOperation::BatchEncrypt(
                UpdateEncryptableMerchantConnectorAccount::to_encryptable(
                    UpdateEncryptableMerchantConnectorAccount {
                        connector_account_details: self.connector_account_details,
                        connector_wallets_details:
                            helpers::get_connector_wallets_details_with_apple_pay_certificates(
                                &self.metadata,
                                &self.connector_wallets_details,
                            )
                            .await?,
                        additional_merchant_data: merchant_recipient_data.map(Secret::new),
                    },
                ),
            ),
            km_types::Identifier::Merchant(
                merchant_context
                    .get_merchant_key_store()
                    .merchant_id
                    .clone(),
            ),
            merchant_context.get_merchant_key_store().key.peek(),
        )
        .await
        .and_then(|val| val.try_into_batchoperation())
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed while decrypting connector account details".to_string())?;

        let encrypted_data =
            UpdateEncryptableMerchantConnectorAccount::from_encryptable(encrypted_data)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed while decrypting connector account details")?;

        Ok(storage::MerchantConnectorAccountUpdate::Update {
            connector_type: Some(self.connector_type),
            connector_name: None,
            merchant_connector_id: None,
            connector_label: self.connector_label.clone(),
            connector_account_details: Box::new(encrypted_data.connector_account_details),
            test_mode: self.test_mode,
            disabled,
            payment_methods_enabled,
            metadata: self.metadata,
            frm_configs,
            connector_webhook_details: match &self.connector_webhook_details {
                Some(connector_webhook_details) => Box::new(
                    connector_webhook_details
                        .encode_to_value()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .map(Some)?
                        .map(Secret::new),
                ),
                None => Box::new(None),
            },
            applepay_verified_domains: None,
            pm_auth_config: Box::new(self.pm_auth_config),
            status: Some(connector_status),
            additional_merchant_data: Box::new(encrypted_data.additional_merchant_data),
            connector_wallets_details: Box::new(encrypted_data.connector_wallets_details),
        })
    }
}

#[cfg(any(feature = "v1", feature = "v2", feature = "olap"))]
#[async_trait::async_trait]
trait MerchantConnectorAccountCreateBridge {
    async fn create_domain_model_from_request(
        self,
        state: &SessionState,
        key_store: domain::MerchantKeyStore,
        business_profile: &domain::Profile,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::MerchantConnectorAccount>;

    async fn validate_and_get_business_profile(
        self,
        merchant_context: &domain::MerchantContext,
        db: &dyn StorageInterface,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::Profile>;
}

#[cfg(all(feature = "v2", feature = "olap"))]
#[async_trait::async_trait]
impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
    async fn create_domain_model_from_request(
        self,
        state: &SessionState,
        key_store: domain::MerchantKeyStore,
        business_profile: &domain::Profile,
        key_manager_state: &KeyManagerState,
    ) -> RouterResult<domain::MerchantConnectorAccount> {
        // If connector label is not passed in the request, generate one
        let connector_label = self.get_connector_label(business_profile.profile_name.clone());
        let frm_configs = self.get_frm_config_as_secret();
        let payment_methods_enabled = self.payment_methods_enabled;
        // Validate Merchant api details and return error if not in correct format
        let auth = types::ConnectorAuthType::from_option_secret_value(
            self.connector_account_details.clone(),
        )
        .change_context(errors::ApiErrorResponse::InvalidDataFormat {
            field_name: "connector_account_details".to_string(),
            expected_format: "auth_type and api_key".to_string(),
        })?;

        let connector_auth_type_and_metadata_validation = ConnectorAuthTypeAndMetadataValidation {
            connector_name: &self.connector_name,
            auth_type: &auth,
            connector_meta_data: &self.metadata,
        };
        connector_auth_type_and_metadata_validation.validate_auth_and_metadata_type()?;
        let connector_status_and_disabled_validation = ConnectorStatusAndDisabledValidation {
            status: &self.status,
            disabled: &self.disabled,
            auth: &auth,
            current_status: &api_enums::ConnectorStatus::Active,
        };
        let (connector_status, disabled) =
            connector_status_and_disabled_validation.validate_status_and_disabled()?;

        let identifier = km_types::Identifier::Merchant(business_profile.merchant_id.clone());
        let merchant_recipient_data = if let Some(data) = &self.additional_merchant_data {
            Some(
                process_open_banking_connectors(
                    state,
                    &business_profile.merchant_id,
                    &auth,
                    &self.connector_type,
                    &self.connector_name,
                    types::AdditionalMerchantData::foreign_from(data.clone()),
                    &key_store,
                )
                .await?,
            )
        } else {
            None
        }
        .map(|data| {
            serde_json::to_value(types::AdditionalMerchantData::OpenBankingRecipientData(
                data,
            ))
        })
        .transpose()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to serialize MerchantRecipientData")?;

        let encrypted_data = domain_types::crypto_operation(
            key_manager_state,
            type_name!(domain::MerchantConnectorAccount),
            domain_types::CryptoOperation::BatchEncrypt(
                FromRequestEncryptableMerchantConnectorAccount::to_encryptable(
                    FromRequestEncryptableMerchantConnectorAccount {
                        connector_account_details: self.connector_account_details.ok_or(
                            errors::ApiErrorResponse::MissingRequiredField {


// Struct: NumberComparison
// File: crates/euclid/src/frontend/ast.rs
// Module: euclid
// Implementations: 0

pub struct NumberComparison


// Struct: AffirmAuthType
// File: crates/hyperswitch_connectors/src/connectors/affirm/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AffirmAuthType


// Function: generate_access_token
// File: crates/router/src/utils/connector_onboarding/paypal.rs
// Module: router

pub fn generate_access_token(state: SessionState) -> RouterResult<types::AccessToken>


// Implementation: impl api::ExternalVaultCreate for for HyperswitchVault
// File: crates/hyperswitch_connectors/src/connectors/hyperswitch_vault.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ExternalVaultCreate for for HyperswitchVault


// Module Structure
// File: crates/hyperswitch_connectors/src/connectors/thunes.rs
// Module: hyperswitch_connectors

// Public submodules:
pub mod transformers;


// Struct: NewUserPassword
// File: crates/router/src/types/domain/user.rs
// Module: router
// Implementations: 1
// Traits: Deref

pub struct NewUserPassword


// File: crates/analytics/src/api_event/types.rs
// Module: analytics

use api_models::analytics::api_event::{ApiEventDimensions, ApiEventFilters};
use error_stack::ResultExt;

use crate::{
    query::{QueryBuilder, QueryFilter, QueryResult, ToSql},
    types::{AnalyticsCollection, AnalyticsDataSource},
};

impl<T> QueryFilter<T> for ApiEventFilters
where
    T: AnalyticsDataSource,
    AnalyticsCollection: ToSql<T>,
{
    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()> {
        if !self.status_code.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::StatusCode, &self.status_code)
                .attach_printable("Error adding status_code filter")?;
        }
        if !self.flow_type.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::FlowType, &self.flow_type)
                .attach_printable("Error adding flow_type filter")?;
        }
        if !self.api_flow.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::ApiFlow, &self.api_flow)
                .attach_printable("Error adding api_name filter")?;
        }

        Ok(())
    }
}


// Implementation: impl Message for for FlatMapEvent
// File: crates/events/src/lib.rs
// Module: events
// Methods: 2 total (0 public)

impl Message for for FlatMapEvent


// File: crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
// Module: hyperswitch_domain_models
// Public structs: 7

use common_enums::Currency;
use common_utils::{id_type, types::MinorUnit};
use time::PrimitiveDateTime;

#[derive(Debug, Clone)]
pub struct SubscriptionCreateResponse {
    pub subscription_id: id_type::SubscriptionId,
    pub status: SubscriptionStatus,
    pub customer_id: id_type::CustomerId,
    pub currency_code: Currency,
    pub total_amount: MinorUnit,
    pub next_billing_at: Option<PrimitiveDateTime>,
    pub created_at: Option<PrimitiveDateTime>,
}

#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum SubscriptionStatus {
    Pending,
    Trial,
    Active,
    Paused,
    Unpaid,
    Onetime,
    Cancelled,
    Failed,
}

#[cfg(feature = "v1")]
impl From<SubscriptionStatus> for api_models::subscription::SubscriptionStatus {
    fn from(status: SubscriptionStatus) -> Self {
        match status {
            SubscriptionStatus::Pending => Self::Pending,
            SubscriptionStatus::Trial => Self::Trial,
            SubscriptionStatus::Active => Self::Active,
            SubscriptionStatus::Paused => Self::Paused,
            SubscriptionStatus::Unpaid => Self::Unpaid,
            SubscriptionStatus::Onetime => Self::Onetime,
            SubscriptionStatus::Cancelled => Self::Cancelled,
            SubscriptionStatus::Failed => Self::Failed,
        }
    }
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionPlansResponse {
    pub list: Vec<SubscriptionPlans>,
}

#[derive(Debug, Clone)]
pub struct SubscriptionPlans {
    pub subscription_provider_plan_id: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionPlanPricesResponse {
    pub list: Vec<SubscriptionPlanPrices>,
}

#[derive(Debug, Clone)]
pub struct SubscriptionPlanPrices {
    pub price_id: String,
    pub plan_id: Option<String>,
    pub amount: MinorUnit,
    pub currency: Currency,
    pub interval: PeriodUnit,
    pub interval_count: i64,
    pub trial_period: Option<i64>,
    pub trial_period_unit: Option<PeriodUnit>,
}

#[derive(Debug, Clone)]
pub enum PeriodUnit {
    Day,
    Week,
    Month,
    Year,
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionEstimateResponse {
    pub sub_total: MinorUnit,
    pub total: MinorUnit,
    pub credits_applied: Option<MinorUnit>,
    pub amount_paid: Option<MinorUnit>,
    pub amount_due: Option<MinorUnit>,
    pub currency: Currency,
    pub next_billing_at: Option<PrimitiveDateTime>,
    pub line_items: Vec<SubscriptionLineItem>,
}

#[derive(Debug, Clone)]
pub struct SubscriptionLineItem {
    pub item_id: String,
    pub item_type: String,
    pub description: String,
    pub amount: MinorUnit,
    pub currency: Currency,
    pub unit_amount: Option<MinorUnit>,
    pub quantity: i64,
    pub pricing_model: Option<String>,
}


// Implementation: impl webhooks::IncomingWebhook for for Novalnet
// File: crates/hyperswitch_connectors/src/connectors/novalnet.rs
// Module: hyperswitch_connectors
// Methods: 7 total (0 public)

impl webhooks::IncomingWebhook for for Novalnet


// Implementation: impl api::ConnectorAccessToken for for Worldpayxml
// File: crates/hyperswitch_connectors/src/connectors/worldpayxml.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Worldpayxml


// Function: user_from_email
// File: crates/router/src/routes/user.rs
// Module: router

pub fn user_from_email(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UserFromEmailRequest>,
) -> HttpResponse


// Implementation: impl PaymentAttemptRecordData
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models
// Methods: 1 total (1 public)

impl PaymentAttemptRecordData


// Module Structure
// File: crates/router/src/routes/dummy_connector.rs
// Module: router

// Public submodules:
pub mod types;


// Struct: BlikDetails
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BlikDetails


// Struct: Attributes
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Attributes


// Struct: MerchantAction
// File: crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MerchantAction


// Implementation: impl GetPaymentMethodDetails for for DummyConnectorUpiType
// File: crates/router/src/routes/dummy_connector/types.rs
// Module: router
// Methods: 2 total (0 public)

impl GetPaymentMethodDetails for for DummyConnectorUpiType


// File: crates/router/tests/connectors/fiuu.rs
// Module: router

use hyperswitch_domain_models::payment_method_data::{Card, PaymentMethodData};
use masking::Secret;
use router::types::{self, api, storage::enums};
use test_utils::connector_auth;

use crate::utils::{self, ConnectorActions};

#[derive(Clone, Copy)]
struct FiuuTest;
impl ConnectorActions for FiuuTest {}
impl utils::Connector for FiuuTest {
    fn get_data(&self) -> api::ConnectorData {
        use router::connector::Fiuu;
        utils::construct_connector_data_old(
            Box::new(Fiuu::new()),
            types::Connector::Plaid,
            api::GetToken::Connector,
            None,
        )
    }

    fn get_auth_token(&self) -> types::ConnectorAuthType {
        utils::to_connector_auth_type(
            connector_auth::ConnectorAuthentication::new()
                .fiuu
                .expect("Missing connector authentication configuration")
                .into(),
        )
    }

    fn get_name(&self) -> String {
        "fiuu".to_string()
    }
}

static CONNECTOR: FiuuTest = FiuuTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    None
}

// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_only_authorize_payment() {
    let response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized);
}

// Captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Partially captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(
            payment_method_details(),
            Some(types::PaymentsCaptureData {
                amount_to_capture: 50,
                ..utils::PaymentCaptureType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_authorized_payment() {
    let authorize_response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Authorized,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("PSync response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
}

// Voids a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_void_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_void_payment(
            payment_method_details(),
            Some(types::PaymentsCancelData {
                connector_transaction_id: String::from(""),
                cancellation_reason: Some("requested_by_customer".to_string()),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Void payment response");
    assert_eq!(response.status, enums::AttemptStatus::Voided);
}

// Refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Synchronizes a refund using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
    let refund_response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_make_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Charged,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                capture_method: Some(enums::CaptureMethod::Automatic),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(response.status, enums::AttemptStatus::Charged,);
}

// Refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
    let response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        refund_response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
    CONNECTOR
        .make_payment_and_multiple_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await;
}

// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_refund() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Cards Negative scenarios
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests


// Implementation: impl Responder
// File: crates/router/src/analytics.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Struct: PaymentMethodIntentConfirmInternal
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 0

pub struct PaymentMethodIntentConfirmInternal


// Struct: TokenDetails
// File: crates/hyperswitch_domain_models/src/router_request_types/unified_authentication_service.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct TokenDetails


// Struct: SantanderValue
// File: crates/hyperswitch_connectors/src/connectors/santander/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SantanderValue


// Implementation: impl MerchantConnectorAccountId
// File: crates/common_utils/src/id_type/merchant_connector_account.rs
// Module: common_utils
// Methods: 1 total (1 public)

impl MerchantConnectorAccountId


// Implementation: impl ConnectorCommon for for Nordea
// File: crates/hyperswitch_connectors/src/connectors/nordea.rs
// Module: hyperswitch_connectors
// Methods: 5 total (0 public)

impl ConnectorCommon for for Nordea


// File: crates/router_env/build.rs
// Module: router_env

mod vergen {
    include!("src/vergen.rs");
}

mod cargo_workspace {
    include!("src/cargo_workspace.rs");
}

fn main() {
    vergen::generate_cargo_instructions();

    cargo_workspace::verify_cargo_metadata_format();
    cargo_workspace::set_cargo_workspace_members_env();
}


// Function: perform_integrity_check
// File: crates/router/src/core/refunds_v2.rs
// Module: router

pub fn perform_integrity_check<F>(
    mut router_data: RouterData<F, types::RefundsData, types::RefundsResponseData>,
) -> RouterData<F, types::RefundsData, types::RefundsResponseData>
where
    F: Debug + Clone + 'static,


// File: crates/router/src/core/mandate/helpers.rs
// Module: router
// Public functions: 2
// Public structs: 1

use api_models::payments as api_payments;
use common_enums::enums;
use common_types::payments as common_payments_types;
use common_utils::errors::CustomResult;
use diesel_models::Mandate;
use error_stack::ResultExt;
use hyperswitch_domain_models::mandates::MandateData;

use crate::{
    core::{errors, payments},
    routes::SessionState,
    types::{api, domain},
};

#[cfg(feature = "v1")]
pub async fn get_profile_id_for_mandate(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    mandate: Mandate,
) -> CustomResult<common_utils::id_type::ProfileId, errors::ApiErrorResponse> {
    let profile_id = if let Some(ref payment_id) = mandate.original_payment_id {
        let pi = state
            .store
            .find_payment_intent_by_payment_id_merchant_id(
                &state.into(),
                payment_id,
                merchant_context.get_merchant_account().get_id(),
                merchant_context.get_merchant_key_store(),
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::PaymentNotFound)?;
        let profile_id =
            pi.profile_id
                .clone()
                .ok_or(errors::ApiErrorResponse::ProfileNotFound {
                    id: pi
                        .profile_id
                        .map(|profile_id| profile_id.get_string_repr().to_owned())
                        .unwrap_or_else(|| "Profile id is Null".to_string()),
                })?;
        Ok(profile_id)
    } else {
        Err(errors::ApiErrorResponse::PaymentNotFound)
    }?;
    Ok(profile_id)
}

pub fn get_mandate_type(
    mandate_data: Option<api_payments::MandateData>,
    off_session: Option<bool>,
    setup_future_usage: Option<enums::FutureUsage>,
    customer_acceptance: Option<common_payments_types::CustomerAcceptance>,
    token: Option<String>,
    payment_method: Option<enums::PaymentMethod>,
) -> CustomResult<Option<api::MandateTransactionType>, errors::ValidationError> {
    match (
        mandate_data.clone(),
        off_session,
        setup_future_usage,
        customer_acceptance.or(mandate_data.and_then(|m_data| m_data.customer_acceptance)),
        token,
        payment_method,
    ) {
        (Some(_), Some(_), Some(enums::FutureUsage::OffSession), Some(_), Some(_), _) => {
            Err(errors::ValidationError::InvalidValue {
                message: "Expected one out of recurring_details and mandate_data but got both"
                    .to_string(),
            }
            .into())
        }
        (_, _, Some(enums::FutureUsage::OffSession), Some(_), Some(_), _)
        | (_, _, Some(enums::FutureUsage::OffSession), Some(_), _, _)
        | (Some(_), _, Some(enums::FutureUsage::OffSession), _, _, _) => {
            Ok(Some(api::MandateTransactionType::NewMandateTransaction))
        }

        (_, _, Some(enums::FutureUsage::OffSession), _, Some(_), _)
        | (_, Some(_), _, _, _, _)
        | (_, _, Some(enums::FutureUsage::OffSession), _, _, Some(enums::PaymentMethod::Wallet)) => {
            Ok(Some(
                api::MandateTransactionType::RecurringMandateTransaction,
            ))
        }

        _ => Ok(None),
    }
}
#[derive(Clone)]
pub struct MandateGenericData {
    pub token: Option<String>,
    pub payment_method: Option<enums::PaymentMethod>,
    pub payment_method_type: Option<enums::PaymentMethodType>,
    pub mandate_data: Option<MandateData>,
    pub recurring_mandate_payment_data:
        Option<hyperswitch_domain_models::router_data::RecurringMandatePaymentData>,
    pub mandate_connector: Option<payments::MandateConnectorDetails>,
    pub payment_method_info: Option<domain::PaymentMethod>,
}


// Function: find_by_merchant_reference_id_profile_id
// File: crates/diesel_models/src/query/payment_intent.rs
// Module: diesel_models

pub fn find_by_merchant_reference_id_profile_id(
        conn: &PgPooledConn,
        merchant_reference_id: &common_utils::id_type::PaymentReferenceId,
        profile_id: &common_utils::id_type::ProfileId,
    ) -> StorageResult<Self>


// Implementation: impl ConnectorSpecifications for for Chargebee
// File: crates/hyperswitch_connectors/src/connectors/chargebee.rs
// Module: hyperswitch_connectors
// Methods: 2 total (0 public)

impl ConnectorSpecifications for for Chargebee


// Implementation: impl Vault
// File: crates/router/src/core/payment_methods/vault.rs
// Module: router
// Methods: 5 total (0 public)

impl Vault


// File: crates/router/src/core/fraud_check/operation/fraud_check_post.rs
// Module: router
// Public structs: 1

use async_trait::async_trait;
use common_enums::{CaptureMethod, FrmSuggestion};
use common_utils::ext_traits::Encode;
use hyperswitch_domain_models::payments::{
    payment_attempt::PaymentAttemptUpdate, payment_intent::PaymentIntentUpdate, HeaderPayload,
};
use router_env::{instrument, logger, tracing};

use super::{Domain, FraudCheckOperation, GetTracker, UpdateTracker};
use crate::{
    consts,
    core::{
        errors::{RouterResult, StorageErrorExt},
        fraud_check::{
            self as frm_core,
            types::{FrmData, PaymentDetails, PaymentToFrmData, CANCEL_INITIATED},
            ConnectorDetailsCore, FrmConfigsObject,
        },
        payments,
    },
    errors,
    routes::app::ReqState,
    services::{self, api},
    types::{
        api::{
            enums::{AttemptStatus, IntentStatus},
            fraud_check as frm_api, payments as payment_types, Capture, Void,
        },
        domain,
        fraud_check::{
            FraudCheckResponseData, FraudCheckSaleData, FrmRequest, FrmResponse, FrmRouterData,
        },
        storage::{
            enums::{FraudCheckLastStep, FraudCheckStatus, FraudCheckType, MerchantDecision},
            fraud_check::{FraudCheckNew, FraudCheckUpdate},
        },
        ResponseId,
    },
    utils, SessionState,
};

#[derive(Debug, Clone, Copy)]
pub struct FraudCheckPost;

impl<F, D> FraudCheckOperation<F, D> for &FraudCheckPost
where
    F: Clone + Send,
    D: payments::OperationSessionGetters<F>
        + payments::OperationSessionSetters<F>
        + Send
        + Sync
        + Clone,
{
    fn to_get_tracker(&self) -> RouterResult<&(dyn GetTracker<PaymentToFrmData> + Send + Sync)> {
        Ok(*self)
    }
    fn to_domain(&self) -> RouterResult<&dyn Domain<F, D>> {
        Ok(*self)
    }
    fn to_update_tracker(&self) -> RouterResult<&(dyn UpdateTracker<FrmData, F, D> + Send + Sync)> {
        Ok(*self)
    }
}

impl<F, D> FraudCheckOperation<F, D> for FraudCheckPost
where
    F: Clone + Send,
    D: payments::OperationSessionGetters<F>
        + payments::OperationSessionSetters<F>
        + Send
        + Sync
        + Clone,
{
    fn to_get_tracker(&self) -> RouterResult<&(dyn GetTracker<PaymentToFrmData> + Send + Sync)> {
        Ok(self)
    }
    fn to_domain(&self) -> RouterResult<&dyn Domain<F, D>> {
        Ok(self)
    }
    fn to_update_tracker(&self) -> RouterResult<&(dyn UpdateTracker<FrmData, F, D> + Send + Sync)> {
        Ok(self)
    }
}

#[async_trait]
impl GetTracker<PaymentToFrmData> for FraudCheckPost {
    #[cfg(feature = "v2")]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_data: PaymentToFrmData,
        frm_connector_details: ConnectorDetailsCore,
    ) -> RouterResult<Option<FrmData>> {
        todo!()
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_data: PaymentToFrmData,
        frm_connector_details: ConnectorDetailsCore,
    ) -> RouterResult<Option<FrmData>> {
        let db = &*state.store;

        let payment_details: Option<serde_json::Value> = PaymentDetails::from(payment_data.clone())
            .encode_to_value()
            .ok();
        let existing_fraud_check = db
            .find_fraud_check_by_payment_id_if_present(
                payment_data.payment_intent.get_id().to_owned(),
                payment_data.merchant_account.get_id().clone(),
            )
            .await
            .ok();
        let fraud_check = match existing_fraud_check {
            Some(Some(fraud_check)) => Ok(fraud_check),
            _ => {
                db.insert_fraud_check_response(FraudCheckNew {
                    frm_id: utils::generate_id(consts::ID_LENGTH, "frm"),
                    payment_id: payment_data.payment_intent.get_id().to_owned(),
                    merchant_id: payment_data.merchant_account.get_id().clone(),
                    attempt_id: payment_data.payment_attempt.attempt_id.clone(),
                    created_at: common_utils::date_time::now(),
                    frm_name: frm_connector_details.connector_name,
                    frm_transaction_id: None,
                    frm_transaction_type: FraudCheckType::PostFrm,
                    frm_status: FraudCheckStatus::Pending,
                    frm_score: None,
                    frm_reason: None,
                    frm_error: None,
                    payment_details,
                    metadata: None,
                    modified_at: common_utils::date_time::now(),
                    last_step: FraudCheckLastStep::Processing,
                    payment_capture_method: payment_data.payment_attempt.capture_method,
                })
                .await
            }
        };
        match fraud_check {
            Ok(fraud_check_value) => {
                let frm_data = FrmData {
                    payment_intent: payment_data.payment_intent,
                    payment_attempt: payment_data.payment_attempt,
                    merchant_account: payment_data.merchant_account,
                    address: payment_data.address,
                    fraud_check: fraud_check_value,
                    connector_details: payment_data.connector_details,
                    order_details: payment_data.order_details,
                    refund: None,
                    frm_metadata: payment_data.frm_metadata,
                };
                Ok(Some(frm_data))
            }
            Err(error) => {
                router_env::logger::error!("inserting into fraud_check table failed {error:?}");
                Ok(None)
            }
        }
    }
}

#[async_trait]
impl<F, D> Domain<F, D> for FraudCheckPost
where
    F: Clone + Send,
    D: payments::OperationSessionGetters<F>
        + payments::OperationSessionSetters<F>
        + Send
        + Sync
        + Clone,
{
    #[instrument(skip_all)]
    async fn post_payment_frm<'a>(
        &'a self,
        state: &'a SessionState,
        _req_state: ReqState,
        payment_data: &mut D,
        frm_data: &mut FrmData,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
    ) -> RouterResult<Option<FrmRouterData>> {
        if frm_data.fraud_check.last_step != FraudCheckLastStep::Processing {
            logger::debug!("post_flow::Sale Skipped");
            return Ok(None);
        }
        let router_data = frm_core::call_frm_service::<F, frm_api::Sale, _, D>(
            state,
            payment_data,
            &mut frm_data.to_owned(),
            merchant_context,
            customer,
        )
        .await?;
        frm_data.fraud_check.last_step = FraudCheckLastStep::CheckoutOrSale;
        Ok(Some(FrmRouterData {
            merchant_id: router_data.merchant_id,
            connector: router_data.connector,
            payment_id: router_data.payment_id.clone(),
            attempt_id: router_data.attempt_id,
            request: FrmRequest::Sale(FraudCheckSaleData {
                amount: router_data.request.amount,
                order_details: router_data.request.order_details,
                currency: router_data.request.currency,
                email: router_data.request.email,
            }),
            response: FrmResponse::Sale(router_data.response),
        }))
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn execute_post_tasks(
        &self,
        _state: &SessionState,
        _req_state: ReqState,
        _frm_data: &mut FrmData,
        _merchant_context: &domain::MerchantContext,
        _frm_configs: FrmConfigsObject,
        _frm_suggestion: &mut Option<FrmSuggestion>,
        _payment_data: &mut D,
        _customer: &Option<domain::Customer>,
        _should_continue_capture: &mut bool,
    ) -> RouterResult<Option<FrmData>> {
        todo!()
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn execute_post_tasks(
        &self,
        state: &SessionState,
        req_state: ReqState,
        frm_data: &mut FrmData,
        merchant_context: &domain::MerchantContext,
        _frm_configs: FrmConfigsObject,
        frm_suggestion: &mut Option<FrmSuggestion>,
        payment_data: &mut D,
        customer: &Option<domain::Customer>,
        _should_continue_capture: &mut bool,
    ) -> RouterResult<Option<FrmData>> {
        if matches!(frm_data.fraud_check.frm_status, FraudCheckStatus::Fraud)
            && matches!(
                frm_data.fraud_check.last_step,
                FraudCheckLastStep::CheckoutOrSale
            )
        {
            *frm_suggestion = Some(FrmSuggestion::FrmCancelTransaction);

            let cancel_req = api_models::payments::PaymentsCancelRequest {
                payment_id: frm_data.payment_intent.get_id().to_owned(),
                cancellation_reason: frm_data.fraud_check.frm_error.clone(),
                merchant_connector_details: None,
            };
            let cancel_res = Box::pin(payments::payments_core::<
                Void,
                payment_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<Void>,
            >(
                state.clone(),
                req_state.clone(),
                merchant_context.clone(),
                None,
                payments::PaymentCancel,
                cancel_req,
                api::AuthFlow::Merchant,
                payments::CallConnectorAction::Trigger,
                None,
                HeaderPayload::default(),
            ))
            .await?;
            logger::debug!("payment_id : {:?} has been cancelled since it has been found fraudulent by configured frm connector",payment_data.get_payment_attempt().payment_id);
            if let services::ApplicationResponse::JsonWithHeaders((payments_response, _)) =
                cancel_res
            {
                payment_data.set_payment_intent_status(payments_response.status);
            }
            let _router_data = frm_core::call_frm_service::<F, frm_api::RecordReturn, _, D>(
                state,
                payment_data,
                &mut frm_data.to_owned(),
                merchant_context,
                customer,
            )
            .await?;
            frm_data.fraud_check.last_step = FraudCheckLastStep::TransactionOrRecordRefund;
        } else if matches!(
            frm_data.fraud_check.frm_status,
            FraudCheckStatus::ManualReview
        ) {
            *frm_suggestion = Some(FrmSuggestion::FrmManualReview);
        } else if matches!(frm_data.fraud_check.frm_status, FraudCheckStatus::Legit)
            && matches!(
                frm_data.fraud_check.payment_capture_method,
                Some(CaptureMethod::Automatic) | Some(CaptureMethod::SequentialAutomatic)
            )
        {
            let capture_request = api_models::payments::PaymentsCaptureRequest {
                payment_id: frm_data.payment_intent.get_id().to_owned(),
                merchant_id: None,
                amount_to_capture: None,
                refund_uncaptured_amount: None,
                statement_descriptor_suffix: None,
                statement_descriptor_prefix: None,
                merchant_connector_details: None,
            };
            let capture_response = Box::pin(payments::payments_core::<
                Capture,
                payment_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<Capture>,
            >(
                state.clone(),
                req_state.clone(),
                merchant_context.clone(),
                None,
                payments::PaymentCapture,
                capture_request,
                api::AuthFlow::Merchant,
                payments::CallConnectorAction::Trigger,
                None,
                HeaderPayload::default(),
            ))
            .await?;
            logger::debug!("payment_id : {:?} has been captured since it has been found legit by configured frm connector",payment_data.get_payment_attempt().payment_id);
            if let services::ApplicationResponse::JsonWithHeaders((payments_response, _)) =
                capture_response
            {
                payment_data.set_payment_intent_status(payments_response.status);
            }
        };
        return Ok(Some(frm_data.to_owned()));
    }

    #[instrument(skip_all)]
    async fn pre_payment_frm<'a>(
        &'a self,
        state: &'a SessionState,
        payment_data: &mut D,
        frm_data: &mut FrmData,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
    ) -> RouterResult<FrmRouterData> {
        let router_data = frm_core::call_frm_service::<F, frm_api::Sale, _, D>(
            state,
            payment_data,
            &mut frm_data.to_owned(),
            merchant_context,
            customer,
        )
        .await?;
        Ok(FrmRouterData {
            merchant_id: router_data.merchant_id,
            connector: router_data.connector,
            payment_id: router_data.payment_id,
            attempt_id: router_data.attempt_id,
            request: FrmRequest::Sale(FraudCheckSaleData {
                amount: router_data.request.amount,
                order_details: router_data.request.order_details,
                currency: router_data.request.currency,
                email: router_data.request.email,
            }),
            response: FrmResponse::Sale(router_data.response),
        })
    }
}

#[async_trait]
impl<F, D> UpdateTracker<FrmData, F, D> for FraudCheckPost
where
    F: Clone + Send,
    D: payments::OperationSessionGetters<F>
        + payments::OperationSessionSetters<F>
        + Send
        + Sync
        + Clone,
{
    #[cfg(feature = "v2")]
    async fn update_tracker<'b>(
        &'b self,
        state: &SessionState,
        key_store: &domain::MerchantKeyStore,
        mut frm_data: FrmData,
        payment_data: &mut D,
        frm_suggestion: Option<FrmSuggestion>,
        frm_router_data: FrmRouterData,
    ) -> RouterResult<FrmData> {
        todo!()
    }

    #[cfg(feature = "v1")]
    async fn update_tracker<'b>(
        &'b self,
        state: &SessionState,
        key_store: &domain::MerchantKeyStore,
        mut frm_data: FrmData,
        payment_data: &mut D,
        frm_suggestion: Option<FrmSuggestion>,
        frm_router_data: FrmRouterData,
    ) -> RouterResult<FrmData> {
        let db = &*state.store;
        let key_manager_state = &state.into();
        let frm_check_update = match frm_router_data.response {
            FrmResponse::Sale(response) => match response {
                Err(err) => Some(FraudCheckUpdate::ErrorUpdate {
                    status: FraudCheckStatus::TransactionFailure,
                    error_message: Some(Some(err.message)),
                }),
                Ok(payments_response) => match payments_response {
                    FraudCheckResponseData::TransactionResponse {
                        resource_id,
                        connector_metadata,
                        status,
                        reason,
                        score,
                    } => {
                        let connector_transaction_id = match resource_id {
                            ResponseId::NoResponseId => None,
                            ResponseId::ConnectorTransactionId(id) => Some(id),
                            ResponseId::EncodedData(id) => Some(id),
                        };

                        let fraud_check_update = FraudCheckUpdate::ResponseUpdate {
                            frm_status: status,
                            frm_transaction_id: connector_transaction_id,
                            frm_reason: reason,
                            frm_score: score,
                            metadata: connector_metadata,
                            modified_at: common_utils::date_time::now(),
                            last_step: frm_data.fraud_check.last_step,
                            payment_capture_method: frm_data.fraud_check.payment_capture_method,
                        };
                        Some(fraud_check_update)
                    },
                    FraudCheckResponseData::RecordReturnResponse { resource_id: _, connector_metadata: _, return_id: _ } => {
                        Some(FraudCheckUpdate::ErrorUpdate {
                            status: FraudCheckStatus::TransactionFailure,
                            error_message: Some(Some(
                                "Error: Got Record Return Response response in current Sale flow".to_string(),
                            )),
                        })
                    }
                    FraudCheckResponseData::FulfillmentResponse {
                        order_id: _,
                        shipment_ids: _,
                    } => None,
                },
            },
            FrmResponse::Fulfillment(response) => match response {
                Err(err) => Some(FraudCheckUpdate::ErrorUpdate {
                    status: FraudCheckStatus::TransactionFailure,
                    error_message: Some(Some(err.message)),
                }),
                Ok(payments_response) => match payments_response {
                    FraudCheckResponseData::TransactionResponse {
                        resource_id,
                        connector_metadata,
                        status,
                        reason,
                        score,
                    } => {
                        let connector_transaction_id = match resource_id {
                            ResponseId::NoResponseId => None,
                            ResponseId::ConnectorTransactionId(id) => Some(id),
                            ResponseId::EncodedData(id) => Some(id),
                        };

                        let fraud_check_update = FraudCheckUpdate::ResponseUpdate {
                            frm_status: status,
                            frm_transaction_id: connector_transaction_id,
                            frm_reason: reason,
                            frm_score: score,
                            metadata: connector_metadata,
                            modified_at: common_utils::date_time::now(),
                            last_step: frm_data.fraud_check.last_step,
                            payment_capture_method: frm_data.fraud_check.payment_capture_method,
                        };
                        Some(fraud_check_update)
                    }
                    FraudCheckResponseData::FulfillmentResponse {
                        order_id: _,
                        shipment_ids: _,
                    } => None,
                    FraudCheckResponseData::RecordReturnResponse { resource_id: _, connector_metadata: _, return_id: _ } => None,

                },
            },

            FrmResponse::RecordReturn(response) => match response {
                Err(err) => Some(FraudCheckUpdate::ErrorUpdate {
                    status: FraudCheckStatus::TransactionFailure,
                    error_message: Some(Some(err.message)),
                }),
                Ok(payments_response) => match payments_response {
                    FraudCheckResponseData::TransactionResponse {
                        resource_id: _,
                        connector_metadata: _,
                        status: _,
                        reason: _,
                        score: _,
                    } => {
                        Some(FraudCheckUpdate::ErrorUpdate {
                            status: FraudCheckStatus::TransactionFailure,
                            error_message: Some(Some(
                                "Error: Got Transaction Response response in current Record Return flow".to_string(),
                            )),
                        })
                    },
                    FraudCheckResponseData::FulfillmentResponse {order_id: _, shipment_ids: _ } => {
                        None
                    },
                    FraudCheckResponseData::RecordReturnResponse { resource_id, connector_metadata, return_id: _ } => {
                        let connector_transaction_id = match resource_id {
                            ResponseId::NoResponseId => None,
                            ResponseId::ConnectorTransactionId(id) => Some(id),
                            ResponseId::EncodedData(id) => Some(id),
                        };

                        let fraud_check_update = FraudCheckUpdate::ResponseUpdate {
                            frm_status: frm_data.fraud_check.frm_status,
                            frm_transaction_id: connector_transaction_id,
                            frm_reason: frm_data.fraud_check.frm_reason.clone(),
                            frm_score: frm_data.fraud_check.frm_score,
                            metadata: connector_metadata,
                            modified_at: common_utils::date_time::now(),
                            last_step: frm_data.fraud_check.last_step,
                            payment_capture_method: frm_data.fraud_check.payment_capture_method,
                        };
                        Some(fraud_check_update)
                    }
                },
            },

            FrmResponse::Checkout(_) | FrmResponse::Transaction(_) => {
                Some(FraudCheckUpdate::ErrorUpdate {
                    status: FraudCheckStatus::TransactionFailure,
                    error_message: Some(Some(
                        "Error: Got Pre(Sale) flow response in current post flow".to_string(),
                    )),
                })
            }
        };

        if let Some(frm_suggestion) = frm_suggestion {
            let (payment_attempt_status, payment_intent_status, merchant_decision, error_message) =
                match frm_suggestion {
                    FrmSuggestion::FrmCancelTransaction => (
                        AttemptStatus::Failure,
                        IntentStatus::Failed,
                        Some(MerchantDecision::Rejected.to_string()),
                        Some(Some(CANCEL_INITIATED.to_string())),
                    ),
                    FrmSuggestion::FrmManualReview => (
                        AttemptStatus::Unresolved,
                        IntentStatus::RequiresMerchantAction,
                        None,
                        None,
                    ),
                    FrmSuggestion::FrmAuthorizeTransaction => (
                        AttemptStatus::Authorized,
                        IntentStatus::RequiresCapture,
                        None,
                        None,
                    ),
                };

            let payment_attempt_update = PaymentAttemptUpdate::RejectUpdate {
                status: payment_attempt_status,
                error_code: Some(Some(frm_data.fraud_check.frm_status.to_string())),
                error_message,
                updated_by: frm_data.merchant_account.storage_scheme.to_string(),
            };

            #[cfg(feature = "v1")]
            let payment_attempt = db
                .update_payment_attempt_with_attempt_id(
                    payment_data.get_payment_attempt().clone(),
                    payment_attempt_update,
                    frm_data.merchant_account.storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

            #[cfg(feature = "v2")]
            let payment_attempt = db
                .update_payment_attempt_with_attempt_id(
                    key_manager_state,
                    key_store,
                    payment_data.get_payment_attempt().clone(),
                    payment_attempt_update,
                    frm_data.merchant_account.storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

            payment_data.set_payment_attempt(payment_attempt);

            let payment_intent = db
                .update_payment_intent(
                    key_manager_state,
                    payment_data.get_payment_intent().clone(),
                    PaymentIntentUpdate::RejectUpdate {
                        status: payment_intent_status,
                        merchant_decision,
                        updated_by: frm_data.merchant_account.storage_scheme.to_string(),
                    },
                    key_store,
                    frm_data.merchant_account.storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

            payment_data.set_payment_intent(payment_intent);
        }
        frm_data.fraud_check = match frm_check_update {
            Some(fraud_check_update) => db
                .update_fraud_check_response_with_attempt_id(
                    frm_data.fraud_check.clone(),
                    fraud_check_update,
                )
                .await
                .map_err(|error| error.change_context(errors::ApiErrorResponse::PaymentNotFound))?,
            None => frm_data.fraud_check.clone(),
        };

        Ok(frm_data)
    }
}


// Struct: RazorpayErrorMessage
// File: crates/hyperswitch_connectors/src/connectors/razorpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RazorpayErrorMessage


// Implementation: impl api::RefundSync for for Forte
// File: crates/hyperswitch_connectors/src/connectors/forte.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for Forte


// Function: create_profile_acquirer
// File: crates/router/src/core/profile_acquirer.rs
// Module: router

pub fn create_profile_acquirer(
    state: SessionState,
    request: profile_acquirer::ProfileAcquirerCreate,
    merchant_context: domain::MerchantContext,
) -> RouterResponse<profile_acquirer::ProfileAcquirerResponse>


// Function: start_process_tracker
// File: crates/scheduler/src/scheduler.rs
// Module: scheduler

pub fn start_process_tracker<
    T: SchedulerAppState + 'static,
    U: SchedulerSessionState + 'static,
    F,
>(
    state: &T,
    scheduler_flow: SchedulerFlow,
    scheduler_settings: Arc<SchedulerSettings>,
    channel: (mpsc::Sender<()


// Function: toggle_specific_dynamic_routing
// File: crates/router/src/core/routing.rs
// Module: router

pub fn toggle_specific_dynamic_routing(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    feature_to_enable: routing::DynamicRoutingFeatures,
    profile_id: common_utils::id_type::ProfileId,
    dynamic_routing_type: routing::DynamicRoutingType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord>


// Struct: Globalpay
// File: crates/hyperswitch_connectors/src/connectors/globalpay.rs
// Module: hyperswitch_connectors
// Implementations: 19
// Traits: ConnectorCommon, ConnectorValidation, PaymentsCompleteAuthorize, api::ConnectorAccessToken, api::Payment, api::PaymentToken, api::MandateSetup, api::PaymentVoid, api::PaymentSync, api::PaymentCapture, api::PaymentSession, api::PaymentAuthorize, api::Refund, api::RefundExecute, api::RefundSync, IncomingWebhook, ConnectorRedirectResponse, ConnectorSpecifications

pub struct Globalpay

ConnectorCommon ConnectorValidation PaymentsCompleteAuthorize api::ConnectorAccessToken api::Payment api::PaymentToken api::MandateSetup api::PaymentVoid api::PaymentSync api::PaymentCapture api::PaymentSession api::PaymentAuthorize api::Refund api::RefundExecute api::RefundSync IncomingWebhook ConnectorRedirectResponse ConnectorSpecifications


// Trait: HealthCheckInterface
// File: crates/drainer/src/health_check.rs
// Module: drainer

pub trait HealthCheckInterface