Test-Implementation Pair

Implementation: crates/router/src/types/storage/payment_attempt.rs
================================================================================
use common_utils::types::MinorUnit;
use diesel_models::{capture::CaptureNew, enums};
use error_stack::ResultExt;
pub use hyperswitch_domain_models::payments::payment_attempt::{
    PaymentAttempt, PaymentAttemptUpdate,
};

use crate::{
    core::errors, errors::RouterResult, types::transformers::ForeignFrom, utils::OptionExt,
};
pub trait PaymentAttemptExt {
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew>;

    fn get_next_capture_id(&self) -> String;
    fn get_total_amount(&self) -> MinorUnit;
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails>;
}

impl PaymentAttemptExt for PaymentAttempt {
    #[cfg(feature = "v2")]
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew> {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew> {
        let capture_sequence = self.multiple_capture_count.unwrap_or_default() + 1;
        let now = common_utils::date_time::now();
        Ok(CaptureNew {
            payment_id: self.payment_id.clone(),
            merchant_id: self.merchant_id.clone(),
            capture_id: self.get_next_capture_id(),
            status: capture_status,
            amount: capture_amount,
            currency: self.currency,
            connector: self
                .connector
                .clone()
                .get_required_value("connector")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "connector field is required in payment_attempt to create a capture",
                )?,
            error_message: None,
            tax_amount: None,
            created_at: now,
            modified_at: now,
            error_code: None,
            error_reason: None,
            authorized_attempt_id: self.attempt_id.clone(),
            capture_sequence,
            connector_capture_id: None,
            connector_response_reference_id: None,
            processor_capture_data: None,
            // Below fields are deprecated. Please add any new fields above this line.
            connector_capture_data: None,
        })
    }

    #[cfg(feature = "v1")]
    fn get_next_capture_id(&self) -> String {
        let next_sequence_number = self.multiple_capture_count.unwrap_or_default() + 1;
        format!("{}_{}", self.attempt_id.clone(), next_sequence_number)
    }

    #[cfg(feature = "v2")]
    fn get_next_capture_id(&self) -> String {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails> {
        self.net_amount
            .get_surcharge_amount()
            .map(
                |surcharge_amount| api_models::payments::RequestSurchargeDetails {
                    surcharge_amount,
                    tax_amount: self.net_amount.get_tax_on_surcharge(),
                },
            )
    }

    #[cfg(feature = "v2")]
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails> {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn get_total_amount(&self) -> MinorUnit {
        self.net_amount.get_total_amount()
    }

    #[cfg(feature = "v2")]
    fn get_total_amount(&self) -> MinorUnit {
        todo!()
    }
}

pub trait AttemptStatusExt {
    fn maps_to_intent_status(self, intent_status: enums::IntentStatus) -> bool;
}

impl AttemptStatusExt for enums::AttemptStatus {
    fn maps_to_intent_status(self, intent_status: enums::IntentStatus) -> bool {
        enums::IntentStatus::foreign_from(self) == intent_status
    }
}

#[cfg(test)]
#[cfg(all(
    feature = "v1", // Ignoring tests for v2 since they aren't actively running
    feature = "dummy_connector"
))]
mod tests {
    use hyperswitch_domain_models::payments::payment_attempt::PaymentAttemptNew;
    use tokio::sync::oneshot;
    use uuid::Uuid;

    use crate::{
        configs::settings::Settings,
        db::StorageImpl,
        routes, services,
        types::{self, storage::enums},
    };

    async fn create_single_connection_test_transaction_pool() -> routes::AppState {
        // Set pool size to 1 and minimum idle connection size to 0
        std::env::set_var("ROUTER__MASTER_DATABASE__POOL_SIZE", "1");
        std::env::set_var("ROUTER__MASTER_DATABASE__MIN_IDLE", "0");
        std::env::set_var("ROUTER__REPLICA_DATABASE__POOL_SIZE", "1");
        std::env::set_var("ROUTER__REPLICA_DATABASE__MIN_IDLE", "0");

        let conf = Settings::new().expect("invalid settings");
        let tx: oneshot::Sender<()> = oneshot::channel().0;
        let api_client = Box::new(services::MockApiClient);
        Box::pin(routes::AppState::with_storage(
            conf,
            StorageImpl::PostgresqlTest,
            tx,
            api_client,
        ))
        .await
    }

    #[tokio::test]
    async fn test_payment_attempt_insert() {
        let state = create_single_connection_test_transaction_pool().await;
        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let current_time = common_utils::date_time::now();
        let connector = types::Connector::DummyConnector1.to_string();
        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            merchant_id: Default::default(),
            attempt_id: Default::default(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            mandate_id: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: None,
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };

        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        let response = store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();
        eprintln!("{response:?}");

        assert_eq!(response.payment_id, payment_id.clone());
    }

    #[tokio::test]
    /// Example of unit test
    /// Kind of test: state-based testing
    async fn test_find_payment_attempt() {
        let state = create_single_connection_test_transaction_pool().await;
        let current_time = common_utils::date_time::now();
        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let attempt_id = Uuid::new_v4().to_string();
        let merchant_id = common_utils::id_type::MerchantId::new_from_unix_timestamp();
        let connector = types::Connector::DummyConnector1.to_string();

        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            merchant_id: merchant_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            attempt_id: attempt_id.clone(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            mandate_id: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: Default::default(),
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };
        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();

        let response = store
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_id,
                &merchant_id,
                &attempt_id,
                enums::MerchantStorageScheme::PostgresOnly,
            )
            .await
            .unwrap();

        eprintln!("{response:?}");

        assert_eq!(response.payment_id, payment_id);
    }

    #[tokio::test]
    /// Example of unit test
    /// Kind of test: state-based testing
    async fn test_payment_attempt_mandate_field() {
        let state = create_single_connection_test_transaction_pool().await;
        let uuid = Uuid::new_v4().to_string();
        let merchant_id =
            common_utils::id_type::MerchantId::try_from(std::borrow::Cow::from("merchant1"))
                .unwrap();

        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let current_time = common_utils::date_time::now();
        let connector = types::Connector::DummyConnector1.to_string();

        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            merchant_id: merchant_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            mandate_id: Some("man_121212".to_string()),
            attempt_id: uuid.clone(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: Default::default(),
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };
        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();

        let response = store
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_id,
                &merchant_id,
                &uuid,
                enums::MerchantStorageScheme::PostgresOnly,
            )
            .await
            .unwrap();
        // checking it after fetch
        assert_eq!(response.mandate_id, Some("man_121212".to_string()));
    }
}

Tests: crates/router/src/types/storage/payment_attempt.rs
================================================================================
use common_utils::types::MinorUnit;
use diesel_models::{capture::CaptureNew, enums};
use error_stack::ResultExt;
pub use hyperswitch_domain_models::payments::payment_attempt::{
    PaymentAttempt, PaymentAttemptUpdate,
};

use crate::{
    core::errors, errors::RouterResult, types::transformers::ForeignFrom, utils::OptionExt,
};
pub trait PaymentAttemptExt {
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew>;

    fn get_next_capture_id(&self) -> String;
    fn get_total_amount(&self) -> MinorUnit;
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails>;
}

impl PaymentAttemptExt for PaymentAttempt {
    #[cfg(feature = "v2")]
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew> {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn make_new_capture(
        &self,
        capture_amount: MinorUnit,
        capture_status: enums::CaptureStatus,
    ) -> RouterResult<CaptureNew> {
        let capture_sequence = self.multiple_capture_count.unwrap_or_default() + 1;
        let now = common_utils::date_time::now();
        Ok(CaptureNew {
            payment_id: self.payment_id.clone(),
            merchant_id: self.merchant_id.clone(),
            capture_id: self.get_next_capture_id(),
            status: capture_status,
            amount: capture_amount,
            currency: self.currency,
            connector: self
                .connector
                .clone()
                .get_required_value("connector")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "connector field is required in payment_attempt to create a capture",
                )?,
            error_message: None,
            tax_amount: None,
            created_at: now,
            modified_at: now,
            error_code: None,
            error_reason: None,
            authorized_attempt_id: self.attempt_id.clone(),
            capture_sequence,
            connector_capture_id: None,
            connector_response_reference_id: None,
            processor_capture_data: None,
            // Below fields are deprecated. Please add any new fields above this line.
            connector_capture_data: None,
        })
    }

    #[cfg(feature = "v1")]
    fn get_next_capture_id(&self) -> String {
        let next_sequence_number = self.multiple_capture_count.unwrap_or_default() + 1;
        format!("{}_{}", self.attempt_id.clone(), next_sequence_number)
    }

    #[cfg(feature = "v2")]
    fn get_next_capture_id(&self) -> String {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails> {
        self.net_amount
            .get_surcharge_amount()
            .map(
                |surcharge_amount| api_models::payments::RequestSurchargeDetails {
                    surcharge_amount,
                    tax_amount: self.net_amount.get_tax_on_surcharge(),
                },
            )
    }

    #[cfg(feature = "v2")]
    fn get_surcharge_details(&self) -> Option<api_models::payments::RequestSurchargeDetails> {
        todo!()
    }

    #[cfg(feature = "v1")]
    fn get_total_amount(&self) -> MinorUnit {
        self.net_amount.get_total_amount()
    }

    #[cfg(feature = "v2")]
    fn get_total_amount(&self) -> MinorUnit {
        todo!()
    }
}

pub trait AttemptStatusExt {
    fn maps_to_intent_status(self, intent_status: enums::IntentStatus) -> bool;
}

impl AttemptStatusExt for enums::AttemptStatus {
    fn maps_to_intent_status(self, intent_status: enums::IntentStatus) -> bool {
        enums::IntentStatus::foreign_from(self) == intent_status
    }
}

#[cfg(test)]
#[cfg(all(
    feature = "v1", // Ignoring tests for v2 since they aren't actively running
    feature = "dummy_connector"
))]
mod tests {
    use hyperswitch_domain_models::payments::payment_attempt::PaymentAttemptNew;
    use tokio::sync::oneshot;
    use uuid::Uuid;

    use crate::{
        configs::settings::Settings,
        db::StorageImpl,
        routes, services,
        types::{self, storage::enums},
    };

    async fn create_single_connection_test_transaction_pool() -> routes::AppState {
        // Set pool size to 1 and minimum idle connection size to 0
        std::env::set_var("ROUTER__MASTER_DATABASE__POOL_SIZE", "1");
        std::env::set_var("ROUTER__MASTER_DATABASE__MIN_IDLE", "0");
        std::env::set_var("ROUTER__REPLICA_DATABASE__POOL_SIZE", "1");
        std::env::set_var("ROUTER__REPLICA_DATABASE__MIN_IDLE", "0");

        let conf = Settings::new().expect("invalid settings");
        let tx: oneshot::Sender<()> = oneshot::channel().0;
        let api_client = Box::new(services::MockApiClient);
        Box::pin(routes::AppState::with_storage(
            conf,
            StorageImpl::PostgresqlTest,
            tx,
            api_client,
        ))
        .await
    }

    #[tokio::test]
    async fn test_payment_attempt_insert() {
        let state = create_single_connection_test_transaction_pool().await;
        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let current_time = common_utils::date_time::now();
        let connector = types::Connector::DummyConnector1.to_string();
        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            merchant_id: Default::default(),
            attempt_id: Default::default(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            mandate_id: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: None,
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };

        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        let response = store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();
        eprintln!("{response:?}");

        assert_eq!(response.payment_id, payment_id.clone());
    }

    #[tokio::test]
    /// Example of unit test
    /// Kind of test: state-based testing
    async fn test_find_payment_attempt() {
        let state = create_single_connection_test_transaction_pool().await;
        let current_time = common_utils::date_time::now();
        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let attempt_id = Uuid::new_v4().to_string();
        let merchant_id = common_utils::id_type::MerchantId::new_from_unix_timestamp();
        let connector = types::Connector::DummyConnector1.to_string();

        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            merchant_id: merchant_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            attempt_id: attempt_id.clone(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            mandate_id: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: Default::default(),
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };
        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();

        let response = store
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_id,
                &merchant_id,
                &attempt_id,
                enums::MerchantStorageScheme::PostgresOnly,
            )
            .await
            .unwrap();

        eprintln!("{response:?}");

        assert_eq!(response.payment_id, payment_id);
    }

    #[tokio::test]
    /// Example of unit test
    /// Kind of test: state-based testing
    async fn test_payment_attempt_mandate_field() {
        let state = create_single_connection_test_transaction_pool().await;
        let uuid = Uuid::new_v4().to_string();
        let merchant_id =
            common_utils::id_type::MerchantId::try_from(std::borrow::Cow::from("merchant1"))
                .unwrap();

        let payment_id =
            common_utils::id_type::PaymentId::generate_test_payment_id_for_sample_data();
        let current_time = common_utils::date_time::now();
        let connector = types::Connector::DummyConnector1.to_string();

        let payment_attempt = PaymentAttemptNew {
            payment_id: payment_id.clone(),
            merchant_id: merchant_id.clone(),
            connector: Some(connector),
            created_at: current_time.into(),
            modified_at: current_time.into(),
            mandate_id: Some("man_121212".to_string()),
            attempt_id: uuid.clone(),
            status: Default::default(),
            net_amount: Default::default(),
            currency: Default::default(),
            save_to_locker: Default::default(),
            error_message: Default::default(),
            offer_amount: Default::default(),
            payment_method_id: Default::default(),
            payment_method: Default::default(),
            capture_method: Default::default(),
            capture_on: Default::default(),
            confirm: Default::default(),
            authentication_type: Default::default(),
            last_synced: Default::default(),
            cancellation_reason: Default::default(),
            amount_to_capture: Default::default(),
            browser_info: Default::default(),
            payment_token: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            payment_experience: Default::default(),
            payment_method_type: Default::default(),
            payment_method_data: Default::default(),
            business_sub_label: Default::default(),
            straight_through_algorithm: Default::default(),
            preprocessing_step_id: Default::default(),
            mandate_details: Default::default(),
            error_reason: Default::default(),
            connector_response_reference_id: Default::default(),
            multiple_capture_count: Default::default(),
            amount_capturable: Default::default(),
            updated_by: Default::default(),
            authentication_data: Default::default(),
            encoded_data: Default::default(),
            merchant_connector_id: Default::default(),
            unified_code: Default::default(),
            unified_message: Default::default(),
            external_three_ds_authentication_attempted: Default::default(),
            authentication_connector: Default::default(),
            authentication_id: Default::default(),
            mandate_data: Default::default(),
            payment_method_billing_address_id: Default::default(),
            fingerprint_id: Default::default(),
            client_source: Default::default(),
            client_version: Default::default(),
            customer_acceptance: Default::default(),
            profile_id: common_utils::generate_profile_id_of_default_length(),
            organization_id: Default::default(),
            connector_mandate_detail: Default::default(),
            request_extended_authorization: Default::default(),
            extended_authorization_applied: Default::default(),
            extended_authorization_last_applied_at: Default::default(),
            capture_before: Default::default(),
            card_discovery: Default::default(),
            processor_merchant_id: Default::default(),
            created_by: None,
            setup_future_usage_applied: Default::default(),
            routing_approach: Default::default(),
            connector_request_reference_id: Default::default(),
            network_transaction_id: Default::default(),
            network_details: Default::default(),
            is_stored_credential: Default::default(),
            authorized_amount: Default::default(),
            tokenization: Default::default(),
        };
        let store = state
            .stores
            .get(state.conf.multitenancy.get_tenant_ids().first().unwrap())
            .unwrap();
        store
            .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly)
            .await
            .unwrap();

        let response = store
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_id,
                &merchant_id,
                &uuid,
                enums::MerchantStorageScheme::PostgresOnly,
            )
            .await
            .unwrap();
        // checking it after fetch
        assert_eq!(response.mandate_id, Some("man_121212".to_string()));
    }
}


Test-Implementation Pair

Implementation: crates/router/src/types/api/payments.rs
================================================================================
#[cfg(feature = "v2")]
pub use api_models::payments::{
    PaymentAttemptListRequest, PaymentAttemptListResponse, PaymentsConfirmIntentRequest,
    PaymentsCreateIntentRequest, PaymentsIntentResponse, PaymentsUpdateIntentRequest,
    RecoveryPaymentsCreate,
};
#[cfg(feature = "v1")]
pub use api_models::payments::{
    PaymentListFilterConstraints, PaymentListResponse, PaymentListResponseV2, PaymentRetrieveBody,
    PaymentRetrieveBodyWithCredentials, PaymentsEligibilityRequest,
};
pub use api_models::{
    feature_matrix::{
        ConnectorFeatureMatrixResponse, FeatureMatrixListResponse, FeatureMatrixRequest,
    },
    payments::{
        Address, AddressDetails, Amount, ApplepayPaymentMethod, AuthenticationForStartResponse,
        Card, CryptoData, CustomerDetails, CustomerDetailsResponse, HyperswitchVaultSessionDetails,
        MandateAmountData, MandateData, MandateTransactionType, MandateType,
        MandateValidationFields, NextActionType, OpenBankingSessionToken, PayLaterData,
        PaymentIdType, PaymentListConstraints, PaymentListFilters, PaymentListFiltersV2,
        PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp,
        PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelPostCaptureRequest,
        PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest,
        PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse,
        PaymentsExtendAuthorizationRequest, PaymentsExternalAuthenticationRequest,
        PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest,
        PaymentsPostSessionTokensRequest, PaymentsPostSessionTokensResponse,
        PaymentsRedirectRequest, PaymentsRedirectionResponse, PaymentsRejectRequest,
        PaymentsRequest, PaymentsResponse, PaymentsResponseForm, PaymentsRetrieveRequest,
        PaymentsSessionRequest, PaymentsSessionResponse, PaymentsStartRequest,
        PaymentsUpdateMetadataRequest, PaymentsUpdateMetadataResponse, PgRedirectResponse,
        PhoneDetails, RedirectionResponse, SessionToken, UrlDetails, VaultSessionDetails,
        VerifyRequest, VerifyResponse, VgsSessionDetails, WalletData,
    },
};
pub use common_types::payments::{AcceptanceType, CustomerAcceptance, OnlineMandate};
use error_stack::ResultExt;
pub use hyperswitch_domain_models::router_flow_types::payments::{
    Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize,
    CreateConnectorCustomer, CreateOrder, ExtendAuthorization, ExternalVaultProxy,
    IncrementalAuthorization, InitPayment, PSync, PaymentCreateIntent, PaymentGetIntent,
    PaymentMethodToken, PaymentUpdateIntent, PostCaptureVoid, PostProcessing, PostSessionTokens,
    PreProcessing, RecordAttempt, Reject, SdkSessionUpdate, Session, SetupMandate, UpdateMetadata,
    Void,
};
pub use hyperswitch_interfaces::api::payments::{
    ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize,
    PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization,
    PaymentPostCaptureVoid, PaymentPostSessionTokens, PaymentReject, PaymentSession,
    PaymentSessionUpdate, PaymentSync, PaymentToken, PaymentUpdateMetadata, PaymentVoid,
    PaymentsCompleteAuthorize, PaymentsCreateOrder, PaymentsPostProcessing, PaymentsPreProcessing,
    TaxCalculation,
};

pub use super::payments_v2::{
    ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2,
    PaymentAuthorizeV2, PaymentCaptureV2, PaymentExtendAuthorizationV2,
    PaymentIncrementalAuthorizationV2, PaymentPostCaptureVoidV2, PaymentPostSessionTokensV2,
    PaymentRejectV2, PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2,
    PaymentUpdateMetadataV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2,
    PaymentsPostProcessingV2, PaymentsPreProcessingV2, TaxCalculationV2,
};
use crate::core::errors;

pub trait PaymentIdTypeExt {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError>;

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError>;
}

impl PaymentIdTypeExt for PaymentIdType {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }
}

pub(crate) trait MandateValidationFieldsExt {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError>;
}

impl MandateValidationFieldsExt for MandateValidationFields {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError> {
        match (&self.mandate_data, &self.recurring_details) {
            (None, None) => Ok(None),
            (Some(_), Some(_)) => Err(errors::ValidationError::InvalidValue {
                message: "Expected one out of recurring_details and mandate_data but got both"
                    .to_string(),
            }
            .into()),
            (_, Some(_)) => Ok(Some(MandateTransactionType::RecurringMandateTransaction)),
            (Some(_), _) => Ok(Some(MandateTransactionType::NewMandateTransaction)),
        }
    }
}

#[cfg(feature = "v1")]
#[cfg(test)]
mod payments_test {
    use super::*;

    #[allow(dead_code)]
    fn card() -> Card {
        Card {
            card_number: "1234432112344321".to_string().try_into().unwrap(),
            card_exp_month: "12".to_string().into(),
            card_exp_year: "99".to_string().into(),
            card_holder_name: Some(masking::Secret::new("JohnDoe".to_string())),
            card_cvc: "123".to_string().into(),
            card_issuer: Some("HDFC".to_string()),
            card_network: Some(api_models::enums::CardNetwork::Visa),
            bank_code: None,
            card_issuing_country: None,
            card_type: None,
            nick_name: Some(masking::Secret::new("nick_name".into())),
        }
    }

    #[allow(dead_code)]
    fn payments_request() -> PaymentsRequest {
        PaymentsRequest {
            amount: Some(Amount::from(common_utils::types::MinorUnit::new(200))),
            payment_method_data: Some(PaymentMethodDataRequest {
                payment_method_data: Some(PaymentMethodData::Card(card())),
                billing: None,
            }),
            ..PaymentsRequest::default()
        }
    }

    //#[test] // FIXME: Fix test
    #[allow(dead_code)]
    fn verify_payments_request() {
        let pay_req = payments_request();
        let serialized =
            serde_json::to_string(&pay_req).expect("error serializing payments request");
        let _deserialized_pay_req: PaymentsRequest =
            serde_json::from_str(&serialized).expect("error de-serializing payments response");
        //assert_eq!(pay_req, deserialized_pay_req)
    }

    // Intended to test the serialization and deserialization of the enum PaymentIdType
    #[test]
    fn test_connector_id_type() {
        let sample_1 = PaymentIdType::PaymentIntentId(
            common_utils::id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
                "test_234565430uolsjdnf48i0",
            ))
            .unwrap(),
        );
        let s_sample_1 = serde_json::to_string(&sample_1).unwrap();
        let ds_sample_1 = serde_json::from_str::<PaymentIdType>(&s_sample_1).unwrap();
        assert_eq!(ds_sample_1, sample_1)
    }
}

Tests: crates/router/src/types/api/payments.rs
================================================================================
#[cfg(feature = "v2")]
pub use api_models::payments::{
    PaymentAttemptListRequest, PaymentAttemptListResponse, PaymentsConfirmIntentRequest,
    PaymentsCreateIntentRequest, PaymentsIntentResponse, PaymentsUpdateIntentRequest,
    RecoveryPaymentsCreate,
};
#[cfg(feature = "v1")]
pub use api_models::payments::{
    PaymentListFilterConstraints, PaymentListResponse, PaymentListResponseV2, PaymentRetrieveBody,
    PaymentRetrieveBodyWithCredentials, PaymentsEligibilityRequest,
};
pub use api_models::{
    feature_matrix::{
        ConnectorFeatureMatrixResponse, FeatureMatrixListResponse, FeatureMatrixRequest,
    },
    payments::{
        Address, AddressDetails, Amount, ApplepayPaymentMethod, AuthenticationForStartResponse,
        Card, CryptoData, CustomerDetails, CustomerDetailsResponse, HyperswitchVaultSessionDetails,
        MandateAmountData, MandateData, MandateTransactionType, MandateType,
        MandateValidationFields, NextActionType, OpenBankingSessionToken, PayLaterData,
        PaymentIdType, PaymentListConstraints, PaymentListFilters, PaymentListFiltersV2,
        PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp,
        PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelPostCaptureRequest,
        PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest,
        PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse,
        PaymentsExtendAuthorizationRequest, PaymentsExternalAuthenticationRequest,
        PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest,
        PaymentsPostSessionTokensRequest, PaymentsPostSessionTokensResponse,
        PaymentsRedirectRequest, PaymentsRedirectionResponse, PaymentsRejectRequest,
        PaymentsRequest, PaymentsResponse, PaymentsResponseForm, PaymentsRetrieveRequest,
        PaymentsSessionRequest, PaymentsSessionResponse, PaymentsStartRequest,
        PaymentsUpdateMetadataRequest, PaymentsUpdateMetadataResponse, PgRedirectResponse,
        PhoneDetails, RedirectionResponse, SessionToken, UrlDetails, VaultSessionDetails,
        VerifyRequest, VerifyResponse, VgsSessionDetails, WalletData,
    },
};
pub use common_types::payments::{AcceptanceType, CustomerAcceptance, OnlineMandate};
use error_stack::ResultExt;
pub use hyperswitch_domain_models::router_flow_types::payments::{
    Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize,
    CreateConnectorCustomer, CreateOrder, ExtendAuthorization, ExternalVaultProxy,
    IncrementalAuthorization, InitPayment, PSync, PaymentCreateIntent, PaymentGetIntent,
    PaymentMethodToken, PaymentUpdateIntent, PostCaptureVoid, PostProcessing, PostSessionTokens,
    PreProcessing, RecordAttempt, Reject, SdkSessionUpdate, Session, SetupMandate, UpdateMetadata,
    Void,
};
pub use hyperswitch_interfaces::api::payments::{
    ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize,
    PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization,
    PaymentPostCaptureVoid, PaymentPostSessionTokens, PaymentReject, PaymentSession,
    PaymentSessionUpdate, PaymentSync, PaymentToken, PaymentUpdateMetadata, PaymentVoid,
    PaymentsCompleteAuthorize, PaymentsCreateOrder, PaymentsPostProcessing, PaymentsPreProcessing,
    TaxCalculation,
};

pub use super::payments_v2::{
    ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2,
    PaymentAuthorizeV2, PaymentCaptureV2, PaymentExtendAuthorizationV2,
    PaymentIncrementalAuthorizationV2, PaymentPostCaptureVoidV2, PaymentPostSessionTokensV2,
    PaymentRejectV2, PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2,
    PaymentUpdateMetadataV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2,
    PaymentsPostProcessingV2, PaymentsPreProcessingV2, TaxCalculationV2,
};
use crate::core::errors;

pub trait PaymentIdTypeExt {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError>;

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError>;
}

impl PaymentIdTypeExt for PaymentIdType {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }
}

pub(crate) trait MandateValidationFieldsExt {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError>;
}

impl MandateValidationFieldsExt for MandateValidationFields {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError> {
        match (&self.mandate_data, &self.recurring_details) {
            (None, None) => Ok(None),
            (Some(_), Some(_)) => Err(errors::ValidationError::InvalidValue {
                message: "Expected one out of recurring_details and mandate_data but got both"
                    .to_string(),
            }
            .into()),
            (_, Some(_)) => Ok(Some(MandateTransactionType::RecurringMandateTransaction)),
            (Some(_), _) => Ok(Some(MandateTransactionType::NewMandateTransaction)),
        }
    }
}

#[cfg(feature = "v1")]
#[cfg(test)]
mod payments_test {
    use super::*;

    #[allow(dead_code)]
    fn card() -> Card {
        Card {
            card_number: "1234432112344321".to_string().try_into().unwrap(),
            card_exp_month: "12".to_string().into(),
            card_exp_year: "99".to_string().into(),
            card_holder_name: Some(masking::Secret::new("JohnDoe".to_string())),
            card_cvc: "123".to_string().into(),
            card_issuer: Some("HDFC".to_string()),
            card_network: Some(api_models::enums::CardNetwork::Visa),
            bank_code: None,
            card_issuing_country: None,
            card_type: None,
            nick_name: Some(masking::Secret::new("nick_name".into())),
        }
    }

    #[allow(dead_code)]
    fn payments_request() -> PaymentsRequest {
        PaymentsRequest {
            amount: Some(Amount::from(common_utils::types::MinorUnit::new(200))),
            payment_method_data: Some(PaymentMethodDataRequest {
                payment_method_data: Some(PaymentMethodData::Card(card())),
                billing: None,
            }),
            ..PaymentsRequest::default()
        }
    }

    //#[test] // FIXME: Fix test
    #[allow(dead_code)]
    fn verify_payments_request() {
        let pay_req = payments_request();
        let serialized =
            serde_json::to_string(&pay_req).expect("error serializing payments request");
        let _deserialized_pay_req: PaymentsRequest =
            serde_json::from_str(&serialized).expect("error de-serializing payments response");
        //assert_eq!(pay_req, deserialized_pay_req)
    }

    // Intended to test the serialization and deserialization of the enum PaymentIdType
    #[test]
    fn test_connector_id_type() {
        let sample_1 = PaymentIdType::PaymentIntentId(
            common_utils::id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
                "test_234565430uolsjdnf48i0",
            ))
            .unwrap(),
        );
        let s_sample_1 = serde_json::to_string(&sample_1).unwrap();
        let ds_sample_1 = serde_json::from_str::<PaymentIdType>(&s_sample_1).unwrap();
        assert_eq!(ds_sample_1, sample_1)
    }
}